UNPKG

@vue-jsx-vapor/compiler

Version:
2,636 lines 94.3 kB
import { parse, parseExpression } from "@babel/parser";
import { NOOP, camelize, canSetValueDirectly, capitalize, extend, isArray, isBuiltInDirective, isGloballyAllowed, isHTMLTag, isSVGTag, isString, isVoidTag, makeMap, remove, shouldSetAsAttr, toHandlerKey } from "@vue/shared";
import { DOMErrorCodes, ErrorCodes, NewlineType, NodeTypes, TS_NODE_TYPES, advancePositionWithClone, advancePositionWithMutation, createCompilerError, createDOMCompilerError, createSimpleExpression, defaultOnError, defaultOnWarn, isConstantNode, isFnExpression, isLiteralWhitelisted, isMemberExpression, isSimpleIdentifier, isStaticProperty, isValidHTMLNesting, locStub, resolveModifiers, toValidAssetId, unwrapTSNode, walkIdentifiers } from "@vue/compiler-dom";
import { walkAST, walkIdentifiers as walkIdentifiers$1 } from "ast-kit";
import { isNodesEquivalent, jsxClosingFragment, jsxExpressionContainer, jsxFragment, jsxOpeningFragment } from "@babel/types";
import { SourceMapGenerator } from "source-map-js";

//#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/transforms/utils.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 jsxFragment(jsxOpeningFragment(), jsxClosingFragment(), [node.type === "JSXElement" ? node : jsxExpressionContainer(node)]);
}
const EMPTY_EXPRESSION = createSimpleExpression("", true);
const isFragmentNode = (node) => node.type === IRNodeTypes.ROOT || node.type === "JSXFragment" || node.type === "JSXElement" && !!isTemplate(node);

//#endregion
//#region src/utils.ts
function propToExpression(prop, context) {
	return prop.type === "JSXAttribute" && prop.value?.type === "JSXExpressionContainer" ? resolveExpression(prop.value.expression, context) : EMPTY_EXPRESSION;
}
function isConstantExpression(exp) {
	return isLiteralWhitelisted(exp.content) || isGloballyAllowed(exp.content) || getLiteralExpressionValue(exp) !== null;
}
function getLiteralExpressionValue(exp) {
	if (exp.ast) {
		if ([
			"StringLiteral",
			"NumericLiteral",
			"BigIntLiteral"
		].includes(exp.ast.type)) return exp.ast.value;
		else if (exp.ast.type === "TemplateLiteral" && exp.ast.expressions.length === 0) return exp.ast.quasis[0].value.cooked;
	}
	return exp.isStatic ? exp.content : null;
}
const isConstant = (node) => {
	if (!node) return false;
	if (node.type === "Identifier") return node.name === "undefined" || isGloballyAllowed(node.name);
	return isConstantNode(node, {});
};
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 resolveSimpleExpressionNode(exp) {
	if (!exp.isStatic) {
		const value = getLiteralExpressionValue(exp);
		if (value !== null) return createSimpleExpression(String(value), true, exp.loc);
	}
	return exp;
}
function resolveExpression(node, context, effect = false) {
	if (!node) return createSimpleExpression("", true);
	node = unwrapTSNode(node.type === "JSXExpressionContainer" ? node.expression : node);
	const isStatic = node.type === "StringLiteral" || node.type === "JSXText" || node.type === "JSXIdentifier";
	let 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);
	const location = node.loc;
	if (source && !isStatic && effect && !isConstant(node)) {
		source = `() => (${source})`;
		node._offset = 7;
	}
	return resolveSimpleExpression(source, isStatic, location, isStatic ? void 0 : node);
}
function resolveSimpleExpression(source, isStatic, location, ast) {
	const result = createSimpleExpression(source, isStatic, resolveLocation(location, source));
	result.ast = ast ?? null;
	return result;
}
function resolveLocation(location, context) {
	return location ? {
		start: {
			line: location.start.line,
			column: location.start.column + 1,
			offset: location.start.index
		},
		end: {
			line: location.end.line,
			column: location.end.column + 1,
			offset: location.end.index
		},
		source: isString(context) ? context : context.ir.source.slice(location.start.index, location.end.index)
	} : {
		start: {
			line: 1,
			column: 1,
			offset: 0
		},
		end: {
			line: 1,
			column: 1,
			offset: 0
		},
		source: ""
	};
}
const namespaceRE = /^(?:\$([\w-]+)\$)?([\w-]+)?/;
function resolveDirective(node, context, withFn = false) {
	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" ? resolveSimpleExpression(argString, isStatic, name.name.loc) : void 0 : resolveSimpleExpression(nameString, true, name.loc);
	const exp = value ? withFn && value.type === "JSXExpressionContainer" ? resolveExpressionWithFn(value.expression, context) : resolveExpression(value, context) : void 0;
	return {
		type: NodeTypes.DIRECTIVE,
		name: isDirective ? nameString.slice(2) : "bind",
		rawName: getText(name, context),
		exp,
		arg,
		loc: resolveLocation(node.loc, context),
		modifiers: modifiers.map((modifier) => createSimpleExpression(modifier))
	};
}
function resolveExpressionWithFn(node, context) {
	const text = getText(node, context);
	return node.type === "Identifier" ? resolveSimpleExpression(text, false, node.loc) : resolveSimpleExpression(text, false, node.loc, parseExpression(`(${text})=>{}`, { plugins: context.options.expressionPlugins }));
}
function isJSXComponent(node) {
	if (node.type !== "JSXElement") return false;
	const { openingElement } = node;
	if (openingElement.name.type === "JSXIdentifier") {
		const name = openingElement.name.name;
		return !isHTMLTag(name) && !isSVGTag(name);
	} else return openingElement.name.type === "JSXMemberExpression";
}
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 && (isString(key) ? name === key : key.test(name))) return attr;
	}
}
function getText(node, content) {
	return content.ir.source.slice(node.start, node.end);
}
function isTemplate(node) {
	if (node.type === "JSXElement" && node.openingElement.name.type === "JSXIdentifier") return node.openingElement.name.name === "template";
}

//#endregion
//#region src/generators/utils.ts
const NEWLINE = Symbol(`newline`);
const INDENT_START = Symbol(`indent start`);
const INDENT_END = Symbol(`indent end`);
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 (!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 = 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 SourceMapGenerator();
		map.setSourceContent(filename, context.ir.source);
		map._sources.add(filename);
	}
	let codegen = "";
	const pos = {
		line: 1,
		column: 1,
		offset: 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 (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.offset += 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 - 1,
			generatedLine: pos.line,
			generatedColumn: pos.column - 1,
			source: filename,
			name
		});
	}
}

//#endregion
//#region src/generators/expression.ts
function genExpression(node, context, assignment) {
	const { content, ast, isStatic, loc } = node;
	if (isStatic) return [[
		JSON.stringify(content),
		NewlineType.None,
		loc
	]];
	if (!node.content.trim() || ast === false || isConstantExpression(node)) return [[
		content,
		NewlineType.None,
		loc
	], assignment && ` = ${assignment}`];
	if (ast === null) return genIdentifier(content, context, loc, assignment);
	const ids = [];
	const parentStackMap = /* @__PURE__ */ new Map();
	const parentStack = [];
	walkIdentifiers$1(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) - (ast._offset || 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),
				source
			}, 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 (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 [
		`${context.options.isTS ? `(_value: any)` : `_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(extend(createSimpleExpression(name, false), { ast: null }), 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, context.options)) {
		handlerExp = genExpression(value, context);
		if (!extraWrap) handlerExp = [
			`e => `,
			...handlerExp,
			`(e)`
		];
	} else if (isFnExpression(value, context.options)) handlerExp = genExpression(value, context);
	else {
		const referencesEvent = value.content.includes("$event");
		const hasMultipleStatements = value.content.includes(`;`);
		const expr = referencesEvent ? context.withId(() => genExpression(value, context), { $event: null }) : genExpression(value, context);
		handlerExp = [
			referencesEvent ? "$event => " : "() => ",
			hasMultipleStatements ? "{" : "(",
			...expr,
			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(capitalize).join("") : "";
	if (node.isStatic) {
		const keyName = (handler ? 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 (isSVGTag(tag)) return helpers.setAttr;
	if (shouldSetAsAttr(tagName, key) || key.includes("-")) return helpers.setAttr;
	return helpers.setProp;
}
function getSpecialHelper(keyName, tagName) {
	if (keyName === "value" && 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(extend(createSimpleExpression(operation.tag, false), { ast: null }), context);
	}
}
function genRawProps(props, context) {
	const staticProps = props[0];
	if (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 (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:${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}`;
			walkIdentifiers$1(props.ast, (id, _, __, ___, isLocal) => {
				if (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);
				const plugins = context.options.expressionPlugins;
				node.ast = parseExpression(`(${path})`, { plugins: plugins ? [...plugins, "typescript"] : ["typescript"] });
			} 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);
	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) walkIdentifiers(value.ast, (id$1, _, parentStack, ___, isLocal) => {
				if (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 === "ArrayPattern") {
							const index$1 = parent.elements.indexOf(child);
							if (child.type === "RestElement") path += `.slice(${index$1})`;
							else path += `[${index$1}]`;
						} else if (parent.type === "ObjectPattern" && child.type === "RestElement") {
							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) {
									isDynamic = true;
									return value.content.slice(p.key.start - 1, p.key.end - 1);
								} else return JSON.stringify(p.key.name);
							}).join(", ")}]`;
						}
						if (child.type === "AssignmentPattern" && (parent.type === "ObjectProperty" || parent.type === "ArrayPattern")) {
							isDynamic = true;
							helper$1 = context.helper("getDefaultValue");
							helperArgs = value.content.slice(child.right.start - 1, child.right.end - 1);
						}
					}
					map.set(id$1.name, {
						path,
						dynamic: isDynamic,
						helper: helper$1,
						helperArgs
					});
				}
			}, true);
			else map.set(rawValue, null);
		}
		return map;
	}
	function genCallback(expr) {
		if (!expr) return false;
		const res = context.withId(() => genExpression(expr, context), genSimpleIdMap());
		return [
			...genMulti([
				"(",
				")",
				", "
			], rawValue ? rawValue : rawKey || rawIndex ? "_" : void 0, rawKey ? rawKey : rawIndex ? "__" : void 0, rawIndex),
			" => (",
			...res,
			")"
		];
	}
	function genSimpleIdMap() {
		const idMap$1 = {};
		if (rawKey) idMap$1[rawKey] = null;
		if (rawIndex) idMap$1[rawIndex] = null;
		idToPathMap.forEach((_, id$1) => idMap$1[id$1] = null);
		return idMap$1;
	}
}
function matchPatterns(render, keyProp, idMap) {
	const selectorPatterns = [];
	const keyOnlyBindingPatterns = [];
	render.effect = render.effect.filter((effect) => {
		if (keyProp !== void 0) {
			const selector = matchSelectorPattern(effect, keyProp.ast, idMap);
			if (selector) {
				selectorPatterns.push(selector);
				return false;
			}
			const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.ast);
			if (keyOnly) {
				keyOnlyBindingPatterns.push(keyOnly);
				return false;
			}
		}
		return true;
	});
	return {
		keyOnlyBindingPatterns,
		selectorPatterns
	};
}
function matchKeyOnlyBindingPattern(effect, keyAst) {
	if (effect.expressions.length === 1) {
		const ast = effect.expressions[0].ast;
		if (typeof ast === "object" && ast !== null && isKeyOnlyBinding(ast, keyAst)) return { effect };
	}
}
function matchSelectorPattern(effect, keyAst, idMap) {
	if (effect.expressions.length === 1) {
		const ast = effect.expressions[0].ast;
		const offset = effect.expressions[0].loc.start.offset;
		if (typeof ast === "object" && ast) {
			const matcheds = [];
			walkAST(ast, { enter(node) {
				if (typeof node === "object" && node && node.type === "BinaryExpression" && node.operator === "===" && node.left.type !== "PrivateName") {
					const { left, right } = node;
					for (const [a, b] of [[left, right], [right, left]]) {
						const aIsKey = isKeyOnlyBinding(a, keyAst);
						const bIsKey = isKeyOnlyBinding(b, keyAst);
						const bVars = analyzeVariableScopes(b, idMap);
						if (aIsKey && !bIsKey && !bVars.locals.length) matcheds.push([a, b]);
					}
				}
			} });
			if (matcheds.length === 1) {
				const [key, selector] = matcheds[0];
				const content$1 = effect.expressions[0].content;
				let hasExtraId = false;
				const parentStackMap = /* @__PURE__ */ new Map();
				const parentStack = [];
				walkIdentifiers(ast, (id) => {
					if (id.start !== key.start && id.start !== selector.start) hasExtraId = true;
					parentStackMap.set(id, parentStack.slice());
				}, false, parentStack);
				if (!hasExtraId) {
					const name = content$1.slice(selector.start - offset, selector.end - offset);
					return {
						effect,
						selector: {
							content: name,
							ast: extend({}, selector, {
								start: 1,
								end: name.length + 1
							}),
							loc: selector.loc,
							isStatic: false
						}
					};
				}
			}
		}
		const content = effect.expressions[0].content;
		if (typeof ast === "object" && ast && ast.type === "ConditionalExpression" && ast.test.type === "BinaryExpression" && ast.test.operator === "===" && ast.test.left.type !== "PrivateName" && isConstant(ast.consequent) && isConstant(ast.alternate)) {
			const left = ast.test.left;
			const right = ast.test.right;
			for (const [a, b] of [[left, right], [right, left]]) {
				const aIsKey = isKeyOnlyBinding(a, keyAst);
				const bIsKey = isKeyOnlyBinding(b, keyAst);
				const bVars = analyzeVariableScopes(b, idMap);
				if (aIsKey && !bIsKey && !bVars.locals.length) return {
					effect,
					selector: {
						content: content.slice(b.start - offset, b.end - offset),
						ast: b,
						loc: b.loc,
						isStatic: false
					}
				};
			}
		}
	}
}
function analyzeVariableScopes(ast, idMap) {
	const globals = [];
	const locals = [];
	const ids = [];
	const parentStackMap = /* @__PURE__ */ new Map();
	const parentStack = [];
	walkIdentifiers(ast, (id) => {
		ids.push(id);
		parentStackMap.set(id, parentStack.slice());
	}, false, parentStack);
	for (const id of ids) {
		if (isGloballyAllowed(id.name)) continue;
		if (idMap[id.name]) locals.push(id.name);
		else globals.push(id.name);
	}
	return {
		globals,
		locals
	};
}
function isKeyOnlyBinding(expr, keyAst) {
	let only = true;
	walkAST(expr, { enter(node) {
		if (isNodesEquivalent(node, keyAst)) {
			this.skip();
			return;
		}
		if (node.type === "Identifier") only = false;
	} });
	return only;
}

//#endregion
//#region src/generators/html.ts
function genSetHtml(oper, context) {
	const { helper } = context;
	const { value, element } = oper;
	return [NEWLINE, ...genCall(helper("setHtml"), `n${element}`, genExpression(value, context))];
}

//#endregion
//#region src/generators/if.ts
function genIf(oper, context, isNested = false) {
	const { helper } = context;
	const { condition, positive, negative, once } = oper;
	const [frag, push] = buildCodeFragment();
	const conditionExpr = [
		"() => (",
		...genExpression(condition, context),
		")"
	];
	const positiveArg = genBlock(positive, context);
	let negativeArg = false;
	if (negative) if (negative.type === IRNodeTypes.BLOCK) negativeArg = genBlock(negative, context);
	else negativeArg = ["() => ", ...genIf(negative, context, true)];
	if (!isNested) push(NEWLINE, `const n${oper.id} = `);
	push(...genCall(helper("createIf"), conditionExpr, positiveArg, negativeArg, once && "true"));
	return frag;
}

//#endregion
//#region src/generators/templateRef.ts
const setTemplateRefIdent = `_setTemplateRef`;
function genSetTemplateRef(oper, context) {
	return [
		NEWLINE,
		oper.effect && `r${oper.element} = `,
		...genCall(setTemplateRefIdent, `n${oper.element}`, genExpression(oper.value, context), oper.effect ? `r${oper.element}` : oper.refFor ? "void 0" : void 0, oper.refFor && "true")
	];
}
function genDeclareOldRef(oper) {
	return [NEWLINE, `let r${oper.id}`];
}

//#endregion
//#region src/generators/text.ts
function genSetText(oper, context) {
	const { helper } = context;
	const { element, values, generated } = oper;
	const texts = combineValues(values, context, true);
	return [NEWLINE, ...genCall(helper("setText"), `${generated ? "x" : "n"}${element}`, texts)];
}
function genGetTextChild(oper, context) {
	return [NEWLINE, `const x${oper.parent} = ${context.helper("child")}(n${oper.parent})`];
}
function genSetNodes(oper, context) {
	const { helper } = context;
	const { element, values, generated } = oper;
	return [NEWLINE, ...genCall(helper("setNodes"), `${generated ? "x" : "n"}${element}`, combineValues(values, context))];
}
function genCreateNodes(oper, context) {
	const { helper } = context;
	const { id, values } = oper;
	return [
		NEWLINE,
		`const n${id} = `,
		...genCall(helper("createNodes"), values && combineValues(values, context))
	];
}
function combineValues(values, context, setText) {
	return values.flatMap((value, i) => {
		let exp = genExpression(value, context);
		if (setText && getLiteralExpressionValue(value) == null) exp = genCall(context.helper("toDisplayString"), exp);
		if (i > 0) exp.unshift(setText ? " + " : ", ");
		return exp;
	});
}

//#endregion
//#region src/generators/operation.ts
function genOperations(opers, context) {
	const [frag, push] = buildCodeFragment();
	for (const operation of opers) push(...genOperationWithInsertionState(operation, context));
	return frag;
}
function genOperationWithInsertionState(oper, context) {
	const [frag, push] = buildCodeFragment();
	if (isBlockOperation(oper) && oper.parent) push(...genInsertionState(oper, context));
	push(...genOperation(oper, context));
	return frag;
}
function genOperation(oper, context) {
	switch (oper.type) {
		case IRNodeTypes.SET_PROP: return genSetProp(oper, context);
		case IRNodeTypes.SET_DYNAMIC_PROPS: return genDynamicProps(oper, context);
		case IRNodeTypes.SET_TEXT: return genSetText(oper, context);
		case IRNodeTypes.SET_EVENT: return genSetEvent(oper, context);
		case IRNodeTypes.SET_DYNAMIC_EVENTS: return genSetDynamicEvents(oper, context);
		case IRNodeTypes.SET_HTML: return genSetHtml(oper, context);
		case IRNodeTypes.SET_TEMPLATE_REF: return genSetTemplateRef(oper, context);
		case IRNodeTypes.INSERT_NODE: return genInsertNode(oper, context);
		case IRNodeTypes.PREPEND_NODE: return genPrependNode(oper, context);
		case IRNodeTypes.IF: return genIf(oper, context);
		case IRNodeTypes.FOR: return genFor(oper, context);
		case IRNodeTypes.CREATE_COMPONENT_NODE: return genCreateComponent(oper, context);
		case IRNodeTypes.DECLARE_OLD_REF: return genDeclareOldRef(oper);
		case IRNodeTypes.SLOT_OUTLET_NODE: return [];
		case IRNodeTypes.DIRECTIVE: return genBuiltinDirective(oper, context);
		case IRNodeTypes.GET_TEXT_CHILD: return genGetTextChild(oper, context);
		case IRNodeTypes.SET_NODES: return genSetNodes(oper, context);
		case IRNodeTypes.CREATE_NODES: return genCreateNodes(oper, context);
		default: {
			const exhaustiveCheck = oper;
			throw new Error(`Unhandled operation type in genOperation: ${exhaustiveCheck}`);
		}
	}
}
function genEffects(effects, context, genExtraFrag) {
	const { helper } = context;
	const [frag, push, unshift] = buildCodeFragment();
	let operationsCount = 0;
	for (const [i, effect] of effects.entries()) {
		operationsCount += effect.operations.length;
		const frags = genEffect(effect, context);
		i > 0 && push(NEWLINE);
		if (frag.at(-1) === ")" && frags[0] === "(") push(";");
		push(...frags);
	}
	const newLineCount = frag.filter((frag$1) => frag$1 === NEWLINE).length;
	if (newLineCount > 1 || operationsCount > 1) {
		unshift(`{`, INDENT_START, NEWLINE);
		push(INDENT_END, NEWLINE, "}");
	}
	if (effects.length) {
		unshift(NEWLINE, `${helper("renderEffect")}(() => `);
		push(`)`);
	}
	if (genExtraFrag) push(...context.withId(genExtraFrag, {}));
	return frag;
}
function genEffect({ operations }, context) {
	const [frag, push] = buildCodeFragment();
	const operationsExps = genOperations(operations, context);
	const newlineCount = operationsExps.filter((frag$1) => frag$1 === NEWLINE).length;
	if (newlineCount > 1) push(...operationsExps);
	else push(...operationsExps.filter((frag$1) => frag$1 !== NEWLINE));
	return frag;
}
function genInsertionState(operation, context) {
	return [NEWLINE, ...genCall(context.helper("setInsertionState"), `n${operation.parent}`, operation.anchor == null ? void 0 : operation.anchor === -1 ? `0` : `n${operation.anchor}`)];
}

//#endregion
//#region src/generators/template.ts
function genTemplates(templates, rootIndex, { helper }) {
	return templates.map((template, i) => template.startsWith("_template") ? template : `${helper("template")}(${JSON.stringify(template)}${i === rootIndex ? ", true" : ""})`);
}
function genSelf(dynamic, context) {
	const [frag, push] = buildCodeFragment();
	const { id, template, operation } = dynamic;
	if (id !== void 0 && template !== void 0) {
		push(NEWLINE, `const n${id} = t${template}()`);
		push(...genDirectivesForElement(id, context));
	}
	if (operation) push(...genOperationWithInsertionState(operation, context));
	return frag;
}
function genChildren(dynamic, context, pushBlock, from = `n${dynamic.id}`) {
	const { helper } = context;
	const [frag, push] = buildCodeFragment();
	const { children } = dynamic;
	let offset = 0;
	let prev;
	const childrenToGen = [];
	for (const [index, child] of children.entries()) {
		if (child.flags & DynamicFlag.NON_TEMPLATE) offset--;
		const id = child.flags & DynamicFlag.REFERENCED ? child.flags & DynamicFlag.INSERT ? child.anchor : child.id : void 0;
		if (id === void 0 && !child.hasDynamicChild) {
			push(...genSelf(child, context));
			continue;
		}
		const elementIndex = Number(index) + offset;
		const variable = id === void 0 ? `p${context.block.tempId++}` : `n${id}`;
		pushBlock(NEWLINE, `const ${variable} = `);
		if (prev) if (elementIndex - prev[1] === 1) pushBlock(...genCall(helper("next"), prev[0]));
		else pushBlock(...genCall(helper("nthChild"), from, String(elementIndex)));
		else if (elementIndex === 0) pushBlock(...genCall(helper("child"), from));
		else {
			let init = genCall(helper("child"), from);
			if (elementIndex === 1) init = genCall(helper("next"), init);
			else if (elementIndex > 1) init = genCall(helper("nthChild"), from, String(elementIndex));
			pushBlock(...init);
		}
		if (id === child.anchor) push(...genSelf(child, context));
		if (id !== void 0) push(...genDirectivesForElement(id, context));
		prev = [variable, elementIndex];
		childrenToGen.push([child, variable]);
	}
	if (childrenToGen.length) for (const [child, from$1] of childrenToGen) push(...genChildren(child, context, pushBlock, from$1));
	return frag;
}

//#endregion
//#region src/generators/block.ts
function genBlock(oper, context, args = [], root) {
	return [
		"(",
		...args,
		") => {",
		INDENT_START,
		...genBlockContent(oper, context, root),
		INDENT_END,
		NEWLINE,
		"}"
	];
}
function genBlockContent(block, context, root, genEffectsExtraFrag) {
	const [frag, push] = buildCodeFragment();
	const { dynamic, effect, operation, returns } = block;
	const resetBlock = context.enterBlock(block);
	if (root) {
		for (let name of context.ir.component) {
			const id = toValidAssetId(name, "component");
			const maybeSelfReference = name.endsWith("__self");
			if (maybeSelfReference) name = name.slice(0, -6);
			push(NEWLINE, `const ${id} = `, ...genCall(context.helper("resolveComponent"), JSON.stringify(name), maybeSelfReference ? "true" : void 0));
		}
		genResolveAssets("directive", "resolveDirective");
	}
	for (const child of dynamic.children) push(...genSelf(child, context));
	for (const child of dynamic.children) push(...genChildren(child, context, push, `n${child.id}`));
	push(...genOperations(operation, context));
	push(...genEffects(effect, context, genEffectsExtraFrag));
	push(NEWLINE, `return `);
	const returnNodes = returns.map((n) => `n${n}`);
	const returnsCode = returnNodes.length > 1 ? genMulti(DELIMITERS_ARRAY, ...returnNodes) : [returnNodes[0] || "null"];
	push(...returnsCode);
	resetBlock();
	return frag;
	function genResolveAssets(kind, helper) {
		for (const name of context.ir[kind]) push(NEWLINE, `const ${toValidAssetId(name, kind)} = `, ...genCall(context.helper(helper), JSON.stringify(name)));
	}
}

//#endregion
//#region src/generate.ts
var CodegenContext = class {
	options;
	helpers = new Set([]);
	helper = (name) => {
		this.helpers.add(name);
		return `_${name}`;
	};
	delegates = /* @__PURE__ */ new Set();
	identifiers = Object.create(null);
	block;
	withId(fn, map) {
		const { identifiers } = this;
		const ids = Object.keys(map);
		for (const id of ids) {
			identifiers[id] ||= [];
			identifiers[id].unshift(map[id] || id);
		}
		const ret = fn();
		ids.forEach((id) => remove(identifiers[id], map[id] || id));
		return ret;
	}
	enterBlock(block) {
		const parent = this.block;
		this.block = block;
		return () => this.block = parent;
	}
	scopeLevel = 0;
	enterScope() {
		return [this.scopeLevel++, () => this.scopeLevel--];
	}
	constructor(ir, options) {
		this.ir = ir;
		const defaultOptions$1 = {
			mode: "module",
			sourceMap: false,
			filename: `template.vue.html`,
			scopeId: null,
			runtimeGlobalName: `Vue`,
			runtimeModuleName: `vue`,
			ssrRuntimeModuleName: "vue/server-renderer",
			ssr: false,
			isTS: false,
			inSSR: false,
			templates: [],
			expressionPlugins: []
		};
		this.options = extend(defaultOptions$1, options);
		this.block = ir.block;
	}
};
function generate(ir, options = {}) {
	const [frag, push] = buildCodeFragment();
	const context = new CodegenContext(ir, options);
	const { helpers: helpers$1 } = context;
	push(INDENT_START);
	if (ir.hasTemplateRef) push(NEWLINE, `const ${setTemplateRefIdent} = ${context.helper("createTemplateRefSetter")}()`);
	push(...genBlockContent(ir.block, context, true));
	push(INDENT_END, NEWLINE);
	if (context.delegates.size) context.helper("delegateEvents");
	const templates = genTemplates(ir.templates, ir.rootTemplateIndex, context);
	const [code, map] = codeFragmentToString(frag, context);
	return {
		code,
		ast: ir,
		map: map && map.toJSON(),
		helpers: helpers$1,
		templates,
		delegates: context.delegates
	};
}

//#endregion
//#region src/transform.ts
const defaultOptions = {
	source: "",
	filename: "",
	hoistStatic: false,
	hmr: false,
	cacheHandlers: false,
	nodeTransforms: [],
	directiveTransforms: {},
	templates: [],
	transformHoist: null,
	isBuiltInComponent: NOOP,
	isCustomElement: NOOP,
	expressionPlugins: [],
	scopeId: null,
	slotted: true,
	ssr: false,
	inSSR: false,
	ssrCssVars: ``,
	isTS: false,
	withFallback: false,
	onError: defaultOnError,
	onWarn: defaultOnWarn
};
var TransformContext = class TransformContext {
	parent = null;
	root;
	index = 0;
	block;
	options;
	template = "";
	childrenTemplate = [];
	dynamic;
	inVOnce = false;
	inVFor = 0;
	comment = [];
	component;
	directive;
	slots = [];
	globalId = 0;
	constructor(ir, node, options = {}) {
		this.ir = ir;
		this.node = node;
		this.options = extend({}, defaultOptions, options);
		this.block = this.ir.block;
		this.dynamic = this.ir.block.dynamic;
		this.component = this.ir.component;
		this.directive = this.ir.directive;
		this.root = this;
	}
	enterBlock(ir, isVFor = false) {
		const { block, template, dynamic, childrenTemplate, slots } = this;
		this.block = ir;
		this.dynamic = ir.dynamic;
		this.template = "";
		this.childrenTemplate = [];
		this.slots = [];
		isVFor && this.inVFor++;
		return () => {
			this.registerTemplate();
			this.block = block;
			this.template = template;
			this.dynamic = dynamic;
			this.childrenTemplate = childrenTemplate;
			this.slots = slots;
			isVFor && this.inVFor--;
		};
	}
	increaseId = () => this.globalId++;
	reference() {
		if (this.dynamic.id !== void 0) return this.dynamic.id;
		this.dynamic.flags |= DynamicFlag.REFERENCED;
		return this.dynamic.id = this.increaseId();
	}
	pushTemplate(content) {
		const existing = this.ir.templates.indexOf(content);
		if (existing !== -1) return existing;
		this.ir.templates.push(content);
		return this.ir.templates.length - 1;
	}
	registerTemplate() {
		if (!this.template) return -1;
		const id = this.pushTemplate(this.template);
		return this.dynamic.template = id;
	}
	registerEffect(expressions, operation, getEffectIndex = () => this.block.effect.length, getOperationIndex = () => this.block.operation.length) {
		const operations = [operation].flat();
		expressions = expressions.filter((exp) => !isConstantExpression(exp));
		if (this.inVOnce || expressions.length === 0 || expressions.every((e) => e.ast && isConstant(e.ast))) return this.registerOperation(operations, getOperationIndex);
		this.block.effect.splice(getEffectIndex(), 0, {
			expressions,
			operations
		});
	}
	registerOperation(operation, getOperationIndex = () => this.block.operation.length) {
		this.block.operation.splice(getOperationIndex(), 0, ...[operation].flat());
	}
	create(node, index) {
		return Object.assign(Object.create(TransformContext.prototype), this, {
			node,
			parent: this,
			index,
			template: "",
			childrenTemplate: [],
			dynamic: newDynamic()
		});
	}
};
function transform(node, options = {}) {
	const ir = {
		type: IRNodeTypes.ROOT,
		node,
		source: node.source,
		templates: options.templates || [],
		component: /* @__PURE__ */ new Set(),
		directive: /* @__PURE__ */ new Set(),
		block: newBlock(node),
		hasTemplateRef: false
	};
	const context = new TransformContext(ir, node, options);
	transformNode(context);
	return ir;
}
function transformNode(context) {
	let { node } = context;
	const { nodeTransforms } = context.options;
	const exitFns = [];
	for (const nodeTransform of nodeTransforms) {
		const onExit = nodeTransform(node, context);
		if (onExit) if (isArray(onExit)) exitFns.push(...onExit);
		else exitFns.push(onExit);
		if (!context.node) return;
		else node = context.node;
	}
	context.node = node;
	let i = exitFns.length;
	while (i--) exitFns[i]();
	if (context.node.type === IRNodeTypes.ROOT) context.registerTemplate();
}
function createStructuralDirectiveTransform(name, fn) {
	const matches = (n) => isString(name) ? n === name : name.includes(n);
	return (node, context) => {
		if (node.type === "JSXElement") {
			const { openingElement: { attributes } } = node;
			if (isTemplate(node) && findProp(node, "v-slot")) return;
			const exitFns = [];
			for (const prop of attributes) {
				if (prop.type !== "JSXAttribute") continue;
				const propName = getText(prop.name, context);
				if (propName.startsWith("v-") && matches(propName.slice(2))) {
					attributes.splice(attributes.indexOf(prop), 1);
					const onExit = fn(node, prop, context);
					if (onExit) exitFns.push(onExit);
					break;
				}
			}
			return exitFns;
		}
	};
}

//#endregion
//#region src/transforms/transformChildren.ts
const transformChildren = (node, context) => {
	const isFragment = node.type === IRNodeTypes.ROOT || node.type === "JSXFragment" || node.type === "JSXElement" && (isTemplate(node) || isJSXComponent(node));
	if (node.type !== "JSXElement" && !isFragment) return;
	for (const [i, child] of node.children.entries()) {
		const childContext = context.create(child, i);
		transformNode(childContext);
		const childDynamic = childContext.dynamic;
		if (isFragment) {
			childContext.reference();
			childContext.registerTemplate();
			if (!(childDynamic.flags & DynamicFlag.NON_TEMPLATE) || childDynamic.flags & DynamicFlag.INSERT) context.block.returns.push(childDynamic.id);
		} else context.childrenTemplate.push(childContext.template);
		if (childDynamic.hasDynamicChild || childDynamic.id !== void 0 || childDynamic.flags & DynamicFlag.NON_TEMPLATE || childDynamic.flags & DynamicFlag.INSERT) context.dynamic.hasDynamicChild = true;
		context.dynamic.children[i] = childContext.dynamic;
	}
	if (!isFragment) processDynamicChildren(context);
};
function processDynamicChildren(context) {
	let prevDynamics = [];
	let hasStaticTemplate = false;
	const children = context.dynamic.children;
	for (const [index, child] of children.entries()) {
		if (child.flags & DynamicFlag.INSERT) prevDynamics.push(child);
		if (!(child.flags & DynamicFlag.NON_TEMPLATE)) {
			if (prevDynamics.length) {
				if (hasStaticTemplate) {
					context.childrenTemplate[index - prevDynamics.length] = `<!>`;
					prevDynamics[0].flags -= DynamicFlag.NON_TEMPLATE;
					const anchor = prevDynamics[0].anchor = context.increaseId();
					registerInsertion(prevDynamics, context, anchor);
				} else registerInsertion(prevDynamics, context, -1);
				prevDynamics = [];
			}
			hasStaticTemplate = true;
		}
	}
	if (prevDynamics.length) registerInsertion(prevDynamics, context);
}
function registerInsertion(dynamics, context, anchor) {
	for (const child of dynamics) if (child.template != null) context.registerOperation({
		type: IRNodeTypes.INSERT_NODE,
		elements: dynamics.map((child$1) => child$1.id),
		parent: context.reference(),
		anchor
	});
	else if (child.operation && isBlockOperation(child.operation)) {
		child.operation.parent = context.reference();
		child.operation.anchor = anchor;
	}
}

//#endregion
//#region src/transforms/transformElement.ts
const isReservedProp = /* @__PURE__ */ makeMap(",key,ref,ref_for,ref_key,");
const isEventRegex = /^on[A-Z]/;
const isDirectiveRegex = /^v-[a-z]/;
const transformElement = (node, context) => {
	let effectIndex = context.block.effect.length;
	const getEffectIndex = () => effectIndex++;
	let operationIndex = context.block.operation.length;
	const getOperationIndex = () => operationIndex++;
	return function postTransformElement() {
		({node} = context);
		if (node.type !== "JSXElement" || isTemplate(node)) return;
		const { openingElement: { name } } = node;
		const tag = name.type === "JSXIdentifier" ? name.name : name.type === "JSXMemberExpression" ? context.ir.source.slice(name.start, name.end) : "";
		const isComponent = isJSXComponent(node);
		const propsResult = buildProps(node, context, isComponent);
		let { parent } = context;
		while (parent && parent.parent && parent.node.type === "JSXElement" && isTemplate(parent.node)) parent = parent.parent;
		const singleRoot = context.root === parent && parent.node.type !== "JSXFragment";
		(isComponent ? transformComponentElement : transformNativeElement)(tag, propsResult, singleRoot, context, getEffectIndex, getOperationIndex);
	};
};
function transformComponentElement(tag, propsResult, singleRoot, context) {
	let asset = context.options.withFallback;
	const dotIndex = tag.indexOf(".");
	if (dotIndex > 0) {
		const ns = tag.slice(0, dotIndex);
		if (ns) tag = ns + tag.slice(dotIndex);
	}
	if (tag.includes("-")) asset = true;
	if (asset) context.component.add(tag);
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT;
	context.dynamic.operation = {
		type: IRNodeTypes.CREATE_COMPONENT_NODE,
		id: context.reference(),
		tag,
		props: propsResult[0] ? propsResult[1] : [propsResult[1]],
		asset,
		root: singleRoot && !context.inVFor,
		slots: [...context.slots],
		once: context.inVOnce
	};
	context.slots = [];
}
function transformNativeElement(tag, propsResult, singleRoot, context, getEffectIndex, getOperationIndex) {
	const { scopeId } = context.options;
	let template = "";
	template += `<${tag}`;
	if (scopeId) template += ` ${scopeId}`;
	const dynamicProps = [];
	if (propsResult[0]) {
		const [, dynamicArgs, expressions] = propsResult;
		context.registerEffect(expressions, {
			type: IRNodeTypes.SET_DYNAMIC_PROPS,
			element: context.reference(),
			props: dynamicArgs,
			root: singleRoot
		}, getEffectIndex, getOperationIndex);
	} else for (const prop of propsResult[1]) {
		const { key, values } = prop;
		if (key.isStatic && values.length === 1 && values[0].isStatic) {
			template += ` ${key.content}`;
			if (values[0].content) template += `="${values[0].content}"`;
		} else {
			dynamicProps.push(key.content);
			context.registerEffect(values, {
				type: IRNodeTypes.SET_PROP,
				element: context.reference(),
				prop,
				tag,
				root: singleRoot
			}, getEffectIndex, getOperationIndex);
		}
	}
	template += `>${context.childrenTemplate.join("")}`;
	if (!isVoidTag(tag)) template += `</${tag}>`;
	if (singleRoot) context.ir.rootTemplateIndex = context.ir.templates.length;
	if (context.parent && context.parent.node.type === "JSXElement" && context.parent.node.openingElement.name.type === "JSXIdentifier" && !isValidHTMLNesting(context.parent.node.openingElement.name.name, tag)) {
		context.reference();
		context.dynamic.template = context.pushTemplate(template);
		context.dynamic.flags |= DynamicFlag.INSERT | DynamicFlag.NON_TEMPLATE;
	} else context.template += template;
}
function buildProps(node, context, isComponent) {
	const props = node.openingElement.attributes;
	if (props.length === 0) return [false, []];
	const dynamicArgs = [];
	const dynamicExpr = [];
	let results = [];
	function pushMergeArg() {
		if (results.length) {
			dynamicArgs.push(dedupeProperties(results));
			results = [];
		}
	}
	for (const prop of props) {
		if (prop.type === "JSXSpreadAttribute" && prop.argument) {
			const value = resolveExpression(prop.argument, context);
			dynamicExpr.push(value);
			pushMergeArg();
			dynamicArgs.push({
				kind: IRDynamicPropsKind.EXPRESSION,
				value
			});
			continue;
		}
		const result = transformProp(prop, node, context);
		if (result) {
			dynamicExpr.push(result.key, result.value);
			if (isComponent && !result.key.isStatic) {
				pushMergeArg();
				dynamicArgs.push(extend(resolveDirectiveResult(result), { kind: IRDynamicPropsKind.ATTRIBUTE }));
			} else results.push(result);
		}
	}
	if (dynamicArgs.length || results.some(({ key }) => !key.isStatic)) {
		pushMergeArg();
		return [
			true,
			dynamicArgs,
			dynamicExpr
		];
	}
	const irProps = dedupeProperties(results);
	return [false, irProps];
}
function transformProp(prop, node, context) {
	if (prop.type === "JSXSpreadAttribute") return;
	let name = prop.name.type === "JSXIdentifier" ? prop.name.name : prop.name.type === "JSXNamespacedName" ? prop.name.namespace.name : "";
	name = name.split("_")[0];
	if (!isDirectiveRegex.test(name) && !isEventRegex.test(name) && (!prop.value || prop.value.type === "StringLiteral")) {
		if (isReservedProp(name)) return;
		return {
			key: resolveSimpleExpression(name, true, prop.name.loc),
			value: prop.value && prop.value.type === "StringLiteral" ? resolveSimpleExpression(prop.value.value, true, prop.value.loc) : createSimpleExpression("true", false)
		};
	}
	name = isEventRegex.test(name) ? "on" : isDirectiveRegex.test(name) ? name.slice(2) : "bind";
	const directiveTransform = context.options.directiveTransforms[name];
	if (directiveTransform) return directiveTransform(prop, node, context);
	if (!isBuiltInDirective(name)) {
		const fromSetup = `v-${name}`;
		if (fromSetup) name = fromSetup;
		else context.directive.add(name);
	}
}
function dedupeProperties(results) {
	const knownProps = /* @__PURE__ */ new Map();
	const deduped = [];
	for (const result of results) {
		const prop = resolveDirectiveResult(result);
		if (!prop.key.isStatic) {
			deduped.push(prop);
			continue;
		}
		const name = prop.key.content;
		const existing = knownProps.get(name);
		if (existing) {
			if (name === "style" || name === "class") mergePropValues(existing, prop);
		} else {
			knownProps.set(name, prop);
			deduped.push(prop);
		}
	}
	return deduped;
}
function resolveDirectiveResult(prop) {
	return extend({}, prop, {
		value: void 0,
		values: [prop.value]
	});
}
function mergePropValues(existing, incoming) {
	const newValues = incoming.values;
	existing.values.push(...newValues);
}

//#endregion
//#region src/transforms/transformTemplateRef.ts
const transformTemplateRef = (node, context) => {
	if (node.type !== "JSXElement") return;
	const dir = findProp(node, "ref");
	if (!dir?.value) return;
	context.ir.hasTemplateRef = true;
	const value = resolveExpression(dir.value, context);
	return () => {
		const id = context.reference();
		const effect = !isConstantExpression(value);
		effect && context.registerOperation({
			type: IRNodeTypes.DECLARE_OLD_REF,
			id
		});
		context.registerEffect([value], {
			type: IRNodeTypes.SET_TEMPLATE_REF,
			element: id,
			value,
			refFor: !!context.inVFor,
			effect
		});
	};
};

//#endregion
//#region src/transforms/expression.ts
function processConditionalExpression(node, context) {
	const { test, consequent, alternate } = node;
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT;
	const id = context.reference();
	const condition = resolveExpression(test, context);
	const [branch, onExit] = createBranch(consequent, context);
	const operation = {
		type: IRNodeTypes.IF,
		id,
		condition,
		positive: branch,
		once: context.inVOnce || isConstant(test)
	};
	return [() => {
		onExit();
		context.dynamic.operation = operation;
	}, () => {
		const [branch$1, onExit$1] = createBranch(alternate, context);
		operation.negative = branch$1;
		transformNode(context);
		onExit$1();
	}];
}
function processLogicalExpression(node, context) {
	const { left, right, operator } = node;
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
	context.dynamic.flags |= DynamicFlag.INSERT;
	const id = context.reference();
	const condition = resolveExpression(left, context);
	const [branch, onExit] = createBranch(operator === "&&" ? right : left, context);
	const operation = {
		type: IRNodeTypes.IF,
		id,
		condition,
		positive: branch,
		once: context.inVOnce
	};
	return [() => {
		onExit();
		context.dynamic.operation = operation;
	}, () => {
		const [branch$1, onExit$1] = createBranch(operator === "&&" ? left : right, context);
		operation.negative = branch$1;
		transformNode(context);
		onExit$1();
	}];
}

//#endregion
//#region src/transforms/transformText.ts
const seen = /* @__PURE__ */ new WeakMap();
function markNonTemplate(node, context) {
	seen.get(context.root).add(node);
}
const transformText = (node, context) => {
	if (!seen.has(context.root)) seen.set(context.root, /* @__PURE__ */ new WeakSet());
	if (seen.get(context.root).has(node)) {
		context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
		return;
	}
	const isFragment = isFragmentNode(node);
	if ((node.type === "JSXElement" && !isTemplate(node) && !isJSXComponent(node) || isFragment) && node.children.length) {
		let hasInterp = false;
		let isAllTextLike = true;
		for (const c of node.children) if (c.type === "JSXExpressionContainer" && c.expression.type !== "ConditionalExpression" && c.expression.type !== "LogicalExpression") hasInterp = true;
		else if (c.type !== "JSXText") isAllTextLike = false;
		if (!isFragment && isAllTextLike && hasInterp) processTextContainer(node.children, context);
		else if (hasInterp) for (let i = 0; i < node.children.length; i++) {
			const c = node.children[i];
			const prev = node.children[i - 1];
			if (c.type === "JSXExpressionContainer" && prev && prev.type === "JSXText") markNonTemplate(prev, context);
		}
	} else if (node.type === "JSXExpressionContainer") if (node.expression.type === "ConditionalExpression") return processConditionalExpression(node.expression, context);
	else if (node.expression.type === "LogicalExpression") return processLogicalExpression(node.expression, context);
	else processInterpolation(context);
	else if (node.type === "JSXText") {
		const value = resolveJSXText(node);
		if (value) context.template += value;
		else context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
	}
};
function processInterpolation(context) {
	const parent = context.parent.node;
	const children = parent.children;
	const nexts = children.slice(context.index);
	const idx = nexts.findIndex((n) => !isTextLike(n));
	const nodes = idx !== -1 ? nexts.slice(0, idx) : nexts;
	const prev = children[context.index - 1];
	if (prev && prev.type === "JSXText") nodes.unshift(prev);
	const values = createTextLikeExpressions(nodes, context);
	if (!values.length) {
		context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
		return;
	}
	const id = context.reference();
	if (isFragmentNode(parent) || findProp(parent, "v-slot")) context.registerOperation({
		type: IRNodeTypes.CREATE_NODES,
		id,
		values
	});
	else {
		context.template += " ";
		context.registerOperation({
			type: IRNodeTypes.SET_NODES,
			element: id,
			values
		});
	}
}
function processTextContainer(children, context) {
	const values = createTextLikeExpressions(children, context);
	const literals = values.map(getLiteralExpressionValue);
	if (literals.every((l) => l != null)) context.childrenTemplate = literals.map((l) => String(l));
	else {
		context.childrenTemplate = [" "];
		context.registerOperation({
			type: IRNodeTypes.GET_TEXT_CHILD,
			parent: context.reference()
		});
		context.registerOperation({
			type: IRNodeTypes.SET_NODES,
			element: context.reference(),
			values,
			generated: true
		});
	}
}
function createTextLikeExpressions(nodes, context) {
	const values = [];
	for (const node of nodes) {
		markNonTemplate(node, context);
		if (isEmptyText(node)) continue;
		values.push(resolveExpression(node, context, !context.inVOnce));
	}
	return values;
}
function isTextLike(node) {
	return node.type === "JSXExpressionContainer" && node.expression.type !== "ConditionalExpression" && node.expression.type !== "LogicalExpression" || node.type === "JSXText";
}

//#endregion
//#region src/transforms/vBind.ts
const transformVBind = (dir, node, context) => {
	const { name, value, loc } = dir;
	if (!loc || name.type === "JSXNamespacedName") return;
	const [nameString, ...modifiers] = name.name.split("_");
	const exp = resolveExpression(value, context);
	let arg = resolveSimpleExpression(nameString, true, dir.name.loc);
	if (arg.isStatic && isReservedProp(arg.content)) return;
	let camel = false;
	if (modifiers.includes("camel")) if (arg.isStatic) arg = extend({}, arg, { content: camelize(arg.content) });
	else camel = true;
	return {
		key: arg,
		value: exp,
		loc,
		runtimeCamelize: camel,
		modifier: modifiers.includes("prop") ? "." : modifiers.includes("attr") ? "^" : void 0
	};
};

//#endregion
//#region src/transforms/vFor.ts
const transformVFor = createStructuralDirectiveTransform("for", processFor);
function processFor(node, dir, context) {
	const { value, index, key, source } = getForParseResult(dir, context);
	if (!source) {
		context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, resolveLocation(dir.loc, context)));
		return;
	}
	const keyProp = findProp(node, "key");
	const keyProperty = keyProp && propToExpression(keyProp, context);
	const isComponent = isJSXComponent(node);
	const id = context.reference();
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT;
	const [render, exitBlock] = createBranch(node, context, true);
	return () => {
		exitBlock();
		const { parent } = context;
		const isOnlyChild = parent && parent.block.node !== parent.node && parent.node.children.filter((child) => !isEmptyText(child)).length === 1;
		context.dynamic.operation = {
			type: IRNodeTypes.FOR,
			id,
			source,
			value,
			key,
			index,
			keyProp: keyProperty,
			render,
			once: context.inVOnce || !!(source.ast && isConstant(source.ast)),
			component: isComponent,
			onlyChild: !!isOnlyChild
		};
	};
}
function getForParseResult(dir, context) {
	let value, index, key, source;
	if (dir.value) {
		if (dir.value.type === "JSXExpressionContainer" && dir.value.expression.type === "BinaryExpression") {
			if (dir.value.expression.left.type === "SequenceExpression") {
				const expressions = dir.value.expression.left.expressions;
				value = expressions[0] && resolveExpressionWithFn(expressions[0], context);
				key = expressions[1] && resolveExpression(expressions[1], context);
				index = expressions[2] && resolveExpression(expressions[2], context);
			} else value = resolveExpressionWithFn(dir.value.expression.left, context);
			source = resolveExpression(dir.value.expression.right, context);
		}
	} else context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, resolveLocation(dir.loc, context)));
	return {
		value,
		index,
		key,
		source
	};
}

//#endregion
//#region src/transforms/vHtml.ts
const transformVHtml = (dir, node, context) => {
	let exp;
	const loc = resolveLocation(dir.loc, context);
	if (!dir.value) {
		context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc));
		exp = EMPTY_EXPRESSION;
	} else exp = resolveExpression(dir.value, context);
	if (node.children.length) {
		context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc));
		context.childrenTemplate.length = 0;
	}
	context.registerEffect([exp], {
		type: IRNodeTypes.SET_HTML,
		element: context.reference(),
		value: exp
	});
};

//#endregion
//#region src/transforms/vIf.ts
const transformVIf = createStructuralDirectiveTransform([
	"if",
	"else",
	"else-if"
], processIf);
const transformedIfNode = /* @__PURE__ */ new WeakMap();
function processIf(node, attribute, context) {
	const dir = resolveDirective(attribute, context);
	if (dir.name !== "else" && (!dir.exp || !dir.exp.content.trim())) {
		const loc = dir.exp ? dir.exp.loc : resolveLocation(node.loc, context);
		context.options.onError(createCompilerError(ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc));
		dir.exp = createSimpleExpression(`true`, false, loc);
	}
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
	transformedIfNode.set(node, dir);
	if (dir.name === "if") {
		const id = context.reference();
		context.dynamic.flags |= DynamicFlag.INSERT;
		const [branch, onExit] = createBranch(node, context);
		return () => {
			onExit();
			context.dynamic.operation = {
				type: IRNodeTypes.IF,
				id,
				condition: dir.exp,
				positive: branch,
				once: context.inVOnce || isConstant(attribute.value)
			};
		};
	} else {
		const siblingIf = getSiblingIf(context);
		const siblings = context.parent && context.parent.dynamic.children;
		let lastIfNode;
		if (siblings) {
			let i = siblings.length;
			while (i--) if (siblings[i].operation && siblings[i].operation.type === IRNodeTypes.IF) {
				lastIfNode = siblings[i].operation;
				break;
			}
		}
		if (!siblingIf || !lastIfNode || lastIfNode.type !== IRNodeTypes.IF) {
			context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, resolveLocation(node.loc, context)));
			return;
		}
		while (lastIfNode.negative && lastIfNode.negative.type === IRNodeTypes.IF) lastIfNode = lastIfNode.negative;
		if (dir.name === "else-if" && lastIfNode.negative) context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, resolveLocation(node.loc, context)));
		context.root.comment = [];
		const [branch, onExit] = createBranch(node, context);
		if (dir.name === "else") lastIfNode.negative = branch;
		else lastIfNode.negative = {
			type: IRNodeTypes.IF,
			id: -1,
			condition: dir.exp,
			positive: branch,
			once: context.inVOnce
		};
		return () => onExit();
	}
}
function getSiblingIf(context) {
	const parent = context.parent;
	if (!parent) return;
	const siblings = parent.node.children;
	let sibling;
	let i = siblings.indexOf(context.node);
	while (--i >= 0) if (!isEmptyText(siblings[i])) {
		sibling = siblings[i];
		break;
	}
	if (sibling && sibling.type === "JSXElement" && transformedIfNode.has(sibling)) return sibling;
}

//#endregion
//#region src/transforms/vModel.ts
const transformVModel = (_dir, node, context) => {
	const dir = resolveDirective(_dir, context);
	const { exp, arg } = dir;
	if (!exp) {
		context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc));
		return;
	}
	const expString = exp.content;
	if (!expString.trim() || !isMemberExpression(exp, context.options)) {
		context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc));
		return;
	}
	const isComponent = isJSXComponent(node);
	if (isComponent) return {
		key: arg ? arg : createSimpleExpression("modelValue", true),
		value: exp,
		model: true,
		modelModifiers: dir.modifiers.map((m) => m.content)
	};
	if (dir.arg) context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT, dir.arg.loc));
	const tag = getText(node.openingElement.name, context);
	const isCustomElement = context.options.isCustomElement(tag);
	let modelType = "text";
	if (tag === "input" || tag === "textarea" || tag === "select" || isCustomElement) if (tag === "input" || isCustomElement) {
		const type = findProp(node, "type");
		if (type?.value) {
			if (type.value.type === "JSXExpressionContainer") modelType = "dynamic";
			else if (type.value.type === "StringLiteral") switch (type.value.value) {
				case "radio":
					modelType = "radio";
					break;
				case "checkbox":
					modelType = "checkbox";
					break;
				case "file":
					modelType = void 0;
					context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT, dir.loc));
					break;
				default:
					checkDuplicatedValue();
					break;
			}
		} else if (hasDynamicKeyVBind(node)) modelType = "dynamic";
		else checkDuplicatedValue();
	} else if (tag === "select") modelType = "select";
	else checkDuplicatedValue();
	else context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT, dir.loc));
	if (modelType) context.registerOperation({
		type: IRNodeTypes.DIRECTIVE,
		element: context.reference(),
		dir,
		name: "model",
		modelType,
		builtin: true
	});
	function checkDuplicatedValue() {
		const value = findProp(node, "value");
		if (value && value.value?.type !== "StringLiteral") context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE, resolveLocation(value.loc, context)));
	}
};
function hasDynamicKeyVBind(node) {
	return node.openingElement.attributes.some((p) => p.type === "JSXSpreadAttribute" || p.type === "JSXAttribute" && p.name.type === "JSXNamespacedName" && !p.name.namespace.name.startsWith("v-"));
}

//#endregion
//#region src/transforms/vOn.ts
const delegatedEvents = /* @__PURE__ */ makeMap("beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,keyup,mousedown,mousemove,mouseout,mouseover,mouseup,pointerdown,pointermove,pointerout,pointerover,pointerup,touchend,touchmove,touchstart");
const transformVOn = (dir, node, context) => {
	const { name, loc, value } = dir;
	if (!name) return;
	const isComponent = isJSXComponent(node);
	const [nameString, ...modifiers] = context.ir.source.slice(name.start, name.end).replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
	if (!value && !modifiers.length) context.options.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, resolveLocation(loc, context)));
	let arg = resolveSimpleExpression(nameString, true, dir.name.loc);
	const exp = resolveExpression(dir.value, context);
	const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(arg.isStatic ? `on${nameString}` : arg, modifiers.map((modifier) => createSimpleExpression(modifier)), null, resolveLocation(loc, context));
	let keyOverride;
	const isStaticClick = arg.isStatic && arg.content.toLowerCase() === "click";
	if (nonKeyModifiers.includes("middle")) {
		if (keyOverride) {}
		if (isStaticClick) arg = extend({}, arg, { content: "mouseup" });
		else if (!arg.isStatic) keyOverride = ["click", "mouseup"];
	}
	if (nonKeyModifiers.includes("right")) {
		if (isStaticClick) arg = extend({}, arg, { content: "contextmenu" });
		else if (!arg.isStatic) keyOverride = ["click", "contextmenu"];
	}
	if (isComponent) {
		const handler = exp || EMPTY_EXPRESSION;
		return {
			key: arg,
			value: handler,
			handler: true,
			handlerModifiers: {
				keys: keyModifiers,
				nonKeys: nonKeyModifiers,
				options: eventOptionModifiers
			}
		};
	}
	const delegate = arg.isStatic && !eventOptionModifiers.length && delegatedEvents(arg.content);
	const operation = {
		type: IRNodeTypes.SET_EVENT,
		element: context.reference(),
		key: arg,
		value: exp,
		modifiers: {
			keys: keyModifiers,
			nonKeys: nonKeyModifiers,
			options: eventOptionModifiers
		},
		keyOverride,
		delegate,
		effect: !arg.isStatic
	};
	context.registerEffect([arg], operation);
};

//#endregion
//#region src/transforms/vOnce.ts
const transformVOnce = (node, context) => {
	if (node.type === "JSXElement" && findProp(node, "v-once")) context.inVOnce = true;
};

//#endregion
//#region src/transforms/vShow.ts
const transformVShow = (_dir, node, context) => {
	const dir = resolveDirective(_dir, context);
	const { exp, loc } = dir;
	if (!exp) {
		context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc));
		return;
	}
	context.registerOperation({
		type: IRNodeTypes.DIRECTIVE,
		element: context.reference(),
		dir,
		name: "show",
		builtin: true
	});
};

//#endregion
//#region src/transforms/vSlot.ts
const transformVSlot = (node, context) => {
	if (node.type !== "JSXElement") return;
	const { children } = node;
	const dir = findProp(node, "v-slot");
	const resolvedDirective = dir ? resolveDirective(dir, context, true) : void 0;
	const { parent } = context;
	const isComponent = isJSXComponent(node);
	const isSlotTemplate = isTemplate(node) && parent && parent.node.type === "JSXElement" && isJSXComponent(parent.node);
	if (isComponent && children.length) return transformComponentSlot(node, resolvedDirective, context);
	else if (isSlotTemplate && resolvedDirective) return transformTemplateSlot(node, resolvedDirective, context);
	else if (!isComponent && dir) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, resolveLocation(dir.loc, context)));
};
function transformComponentSlot(node, dir, context) {
	const { children } = node;
	const arg = dir && dir.arg;
	const nonSlotTemplateChildren = children.filter((n) => !isEmptyText(n) && (n.type !== "JSXElement" || !findProp(n, "v-slot")));
	const [block, onExit] = createSlotBlock(node, dir, context);
	const { slots } = context;
	return () => {
		onExit();
		const hasOtherSlots = !!slots.length;
		if (dir && hasOtherSlots) {
			context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, dir.loc));
			return;
		}
		if (nonSlotTemplateChildren.length) if (hasStaticSlot(slots, "default")) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN, resolveLocation(nonSlotTemplateChildren[0].loc, context)));
		else {
			registerSlot(slots, arg, block);
			context.slots = slots;
		}
		else if (hasOtherSlots) context.slots = slots;
	};
}
const elseIfRE = /^v-else(-if)?$/;
function transformTemplateSlot(node, dir, context) {
	context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
	const arg = dir.arg && resolveSimpleExpressionNode(dir.arg);
	const vFor = findProp(node, "v-for");
	const vIf = findProp(node, "v-if");
	const vElse = findProp(node, elseIfRE);
	const { slots } = context;
	const [block, onExit] = createSlotBlock(node, dir, context);
	if (!vFor && !vIf && !vElse) {
		const slotName = arg ? arg.isStatic && arg.content : "default";
		if (slotName && hasStaticSlot(slots, slotName)) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES, dir.loc));
		else registerSlot(slots, arg, block);
	} else if (vIf) {
		const vIfDir = resolveDirective(vIf, context);
		registerDynamicSlot(slots, {
			slotType: IRSlotType.CONDITIONAL,
			condition: vIfDir.exp,
			positive: {
				slotType: IRSlotType.DYNAMIC,
				name: arg,
				fn: block
			}
		});
	} else if (vElse) {
		const vElseDir = resolveDirective(vElse, context);
		const vIfSlot = slots.at(-1);
		if (vIfSlot.slotType === IRSlotType.CONDITIONAL) {
			let ifNode = vIfSlot;
			while (ifNode.negative && ifNode.negative.slotType === IRSlotType.CONDITIONAL) ifNode = ifNode.negative;
			const negative = vElseDir.exp ? {
				slotType: IRSlotType.CONDITIONAL,
				condition: vElseDir.exp,
				positive: {
					slotType: IRSlotType.DYNAMIC,
					name: arg,
					fn: block
				}
			} : {
				slotType: IRSlotType.DYNAMIC,
				name: arg,
				fn: block
			};
			ifNode.negative = negative;
		} else context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElseDir.loc));
	} else if (vFor) {
		const forParseResult = getForParseResult(vFor, context);
		if (forParseResult.source) registerDynamicSlot(slots, {
			slotType: IRSlotType.LOOP,
			name: arg,
			fn: block,
			loop: forParseResult
		});
	}
	return onExit;
}
function ensureStaticSlots(slots) {
	let lastSlots = slots.at(-1);
	if (!slots.length || lastSlots.slotType !== IRSlotType.STATIC) slots.push(lastSlots = {
		slotType: IRSlotType.STATIC,
		slots: {}
	});
	return lastSlots.slots;
}
function registerSlot(slots, name, block) {
	const isStatic = !name || name.isStatic;
	if (isStatic) {
		const staticSlots = ensureStaticSlots(slots);
		staticSlots[name ? name.content : "default"] = block;
	} else slots.push({
		slotType: IRSlotType.DYNAMIC,
		name,
		fn: block
	});
}
function registerDynamicSlot(allSlots, dynamic) {
	allSlots.push(dynamic);
}
function hasStaticSlot(slots, name) {
	return slots.some((slot) => slot.slotType === IRSlotType.STATIC ? !!slot.slots[name] : false);
}
function createSlotBlock(slotNode, dir, context) {
	const block = newBlock(slotNode);
	block.props = dir && dir.exp;
	const exitBlock = context.enterBlock(block);
	return [block, exitBlock];
}

//#endregion
//#region src/transforms/vSlots.ts
const transformVSlots = (dir, node, context) => {
	if (!isJSXComponent(node)) return;
	if (dir.value?.type === "JSXExpressionContainer") context.slots = [{
		slotType: IRSlotType.EXPRESSION,
		slots: resolveExpression(dir.value.expression, context)
	}];
};

//#endregion
//#region src/transforms/vText.ts
const transformVText = (dir, node, context) => {
	let exp;
	const loc = resolveLocation(dir.loc, context);
	if (!dir.value) {
		context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc));
		exp = EMPTY_EXPRESSION;
	} else exp = resolveExpression(dir.value, context);
	if (node.children.length) {
		context.options.onError(createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc));
		context.childrenTemplate.length = 0;
	}
	if (isVoidTag(getText(node.openingElement.name, context))) return;
	const literal = getLiteralExpressionValue(exp);
	if (literal != null) context.childrenTemplate = [String(literal)];
	else {
		context.childrenTemplate = [" "];
		context.registerOperation({
			type: IRNodeTypes.GET_TEXT_CHILD,
			parent: context.reference()
		});
		context.registerEffect([exp], {
			type: IRNodeTypes.SET_TEXT,
			element: context.reference(),
			values: [exp],
			generated: true
		});
	}
};

//#endregion
//#region src/compile.ts
function compile(source, options = {}) {
	const resolvedOptions = extend({}, options, { expressionPlugins: options.expressionPlugins || ["jsx"] });
	if (!resolvedOptions.source && isString(source)) resolvedOptions.source = source;
	if (resolvedOptions.isTS) {
		const { expressionPlugins } = resolvedOptions;
		if (!expressionPlugins.includes("typescript")) resolvedOptions.expressionPlugins = [...expressionPlugins || [], "typescript"];
	}
	const root = isString(source) ? parse(source, {
		sourceType: "module",
		plugins: resolvedOptions.expressionPlugins
	}).program.body[0].expression : source;
	const children = root.type === "JSXFragment" ? root.children : root.type === "JSXElement" ? [root] : [];
	const ast = {
		type: IRNodeTypes.ROOT,
		children,
		source: resolvedOptions.source || ""
	};
	const [nodeTransforms, directiveTransforms] = getBaseTransformPreset();
	const ir = transform(ast, extend({}, resolvedOptions, {
		nodeTransforms: [...nodeTransforms, ...resolvedOptions.nodeTransforms || []],
		directiveTransforms: extend({}, directiveTransforms, resolvedOptions.directiveTransforms || {})
	}));
	return generate(ir, resolvedOptions);
}
function getBaseTransformPreset() {
	return [[
		transformVOnce,
		transformVIf,
		transformVFor,
		transformTemplateRef,
		transformElement,
		transformText,
		transformVSlot,
		transformChildren
	], {
		bind: transformVBind,
		on: transformVOn,
		model: transformVModel,
		show: transformVShow,
		html: transformVHtml,
		text: transformVText,
		slots: transformVSlots
	}];
}

//#endregion
export { CodegenContext, DynamicFlag, IRDynamicPropsKind, IRNodeTypes, IRSlotType, TransformContext, compile, createStructuralDirectiveTransform, generate, isBlockOperation, transform, transformChildren, transformElement, transformNode, transformTemplateRef, transformText, transformVBind, transformVFor, transformVHtml, transformVIf, transformVModel, transformVOn, transformVOnce, transformVShow, transformVSlot, transformVSlots, transformVText };