@vue-jsx-vapor/macros
Version:
Macros for Vue JSX Vapor
1,053 lines (1,036 loc) • 43.5 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) {
__defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
require("@babel/parser");
let magic_string = require("magic-string");
magic_string = __toESM(magic_string);
let hash_sum = require("hash-sum");
hash_sum = __toESM(hash_sum);
//#region ../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
function normalizeWindowsPath(input = "") {
if (!input) return input;
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
}
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
const extname = function(p) {
if (p === "..") return "";
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
return match && match[1] || "";
};
//#endregion
//#region ../../node_modules/.pnpm/ast-kit@2.2.0/node_modules/ast-kit/dist/index.js
/**
* Checks if the given node is a function type.
*
* @param node - The node to check.
* @returns True if the node is a function type, false otherwise.
*/
function isFunctionType(node) {
return !!node && !node.type.startsWith("TS") && /Function(?:Expression|Declaration)$|Method$/.test(node.type);
}
/* v8 ignore next -- @preserve */
/**
* Checks if the input `node` is a reference to a bound variable.
*
* Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts
*
* To avoid runtime dependency on `@babel/types` (which includes process references)
* This file should not change very often in babel but we may need to keep it
* up-to-date from time to time.
*
* @param node - The node to check.
* @param parent - The parent node of the input `node`.
* @param grandparent - The grandparent node of the input `node`.
* @returns True if the input `node` is a reference to a bound variable, false otherwise.
*/
function isReferenced(node, parent, grandparent) {
switch (parent.type) {
case "MemberExpression":
case "OptionalMemberExpression":
if (parent.property === node) return !!parent.computed;
return parent.object === node;
case "JSXMemberExpression": return parent.object === node;
case "VariableDeclarator": return parent.init === node;
case "ArrowFunctionExpression": return parent.body === node;
case "PrivateName": return false;
case "ClassMethod":
case "ClassPrivateMethod":
case "ObjectMethod":
if (parent.key === node) return !!parent.computed;
return false;
case "ObjectProperty":
if (parent.key === node) return !!parent.computed;
return !grandparent || grandparent.type !== "ObjectPattern";
case "ClassProperty":
case "ClassAccessorProperty":
if (parent.key === node) return !!parent.computed;
return true;
case "ClassPrivateProperty": return parent.key !== node;
case "ClassDeclaration":
case "ClassExpression": return parent.superClass === node;
case "AssignmentExpression": return parent.right === node;
case "AssignmentPattern": return parent.right === node;
case "LabeledStatement": return false;
case "CatchClause": return false;
case "RestElement": return false;
case "BreakStatement":
case "ContinueStatement": return false;
case "FunctionDeclaration":
case "FunctionExpression": return false;
case "ExportNamespaceSpecifier":
case "ExportDefaultSpecifier": return false;
case "ExportSpecifier":
if (grandparent?.source) return false;
return parent.local === node;
case "ImportDefaultSpecifier":
case "ImportNamespaceSpecifier":
case "ImportSpecifier": return false;
case "ImportAttribute": return false;
case "JSXAttribute":
case "JSXNamespacedName": return false;
case "ObjectPattern":
case "ArrayPattern": return false;
case "MetaProperty": return false;
case "ObjectTypeProperty": return parent.key !== node;
case "TSEnumMember": return parent.id !== node;
case "TSPropertySignature":
if (parent.key === node) return !!parent.computed;
return true;
}
return true;
}
function isIdentifier(node) {
return !!node && (node.type === "Identifier" || node.type === "JSXIdentifier");
}
function isForStatement(stmt) {
return stmt.type === "ForOfStatement" || stmt.type === "ForInStatement" || stmt.type === "ForStatement";
}
function isReferencedIdentifier(id, parent, parentStack) {
if (!parent) return true;
if (id.name === "arguments") return false;
if (isReferenced(id, parent, parentStack.at(-2))) return true;
switch (parent.type) {
case "AssignmentExpression":
case "AssignmentPattern": return true;
case "ObjectProperty": return parent.key !== id && isInDestructureAssignment(parent, parentStack);
case "ArrayPattern": return isInDestructureAssignment(parent, parentStack);
}
return false;
}
function isInDestructureAssignment(parent, parentStack) {
if (parent && (parent.type === "ObjectProperty" || parent.type === "ArrayPattern")) {
let i = parentStack.length;
while (i--) {
const p = parentStack[i];
if (p.type === "AssignmentExpression") return true;
else if (p.type !== "ObjectProperty" && !p.type.endsWith("Pattern")) break;
}
}
return false;
}
/**
* Extract identifiers of the given node.
* @param node The node to extract.
* @param identifiers The array to store the extracted identifiers.
* @see https://github.com/vuejs/core/blob/1f6a1102aa09960f76a9af2872ef01e7da8538e3/packages/compiler-core/src/babelUtils.ts#L208
*/
function extractIdentifiers(node, identifiers = []) {
switch (node.type) {
case "Identifier":
case "JSXIdentifier":
identifiers.push(node);
break;
case "MemberExpression":
case "JSXMemberExpression": {
let object = node;
while (object.type === "MemberExpression") object = object.object;
identifiers.push(object);
break;
}
case "ObjectPattern":
for (const prop of node.properties) if (prop.type === "RestElement") extractIdentifiers(prop.argument, identifiers);
else extractIdentifiers(prop.value, identifiers);
break;
case "ArrayPattern":
node.elements.forEach((element) => {
element && extractIdentifiers(element, identifiers);
});
break;
case "RestElement":
extractIdentifiers(node.argument, identifiers);
break;
case "AssignmentPattern":
extractIdentifiers(node.left, identifiers);
break;
}
return identifiers;
}
const REGEX_DTS = /\.d\.[cm]?ts(\?.*)?$/;
/**
* Returns the language (extension name) of a given filename.
* @param filename - The name of the file.
* @returns The language of the file.
*/
function getLang(filename) {
if (isDts(filename)) return "dts";
return extname(filename).replace(/^\./, "").replace(/\?.*$/, "");
}
/**
* Checks if a filename represents a TypeScript declaration file (.d.ts).
* @param filename - The name of the file to check.
* @returns A boolean value indicating whether the filename is a TypeScript declaration file.
*/
function isDts(filename) {
return REGEX_DTS.test(filename);
}
/**
* @typedef { import('estree').Node} Node
* @typedef {{
* skip: () => void;
* remove: () => void;
* replace: (node: Node) => void;
* }} WalkerContext
*/
var WalkerBase = class {
constructor() {
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => this.should_skip = true,
remove: () => this.should_remove = true,
replace: (node) => this.replacement = node
};
}
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
* @param {Node} node
*/
replace(parent, prop, index, node) {
if (parent && prop) if (index != null)
/** @type {Array<Node>} */ parent[prop][index] = node;
else
/** @type {Node} */ parent[prop] = node;
}
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
*/
remove(parent, prop, index) {
if (parent && prop) if (index !== null && index !== void 0)
/** @type {Array<Node>} */ parent[prop].splice(index, 1);
else delete parent[prop];
}
};
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => void} SyncHandler
*/
var SyncWalker = class extends WalkerBase {
/**
*
* @param {SyncHandler} [enter]
* @param {SyncHandler} [leave]
*/
constructor(enter, leave) {
super();
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => this.should_skip = true,
remove: () => this.should_remove = true,
replace: (node) => this.replacement = node
};
/** @type {SyncHandler | undefined} */
this.enter = enter;
/** @type {SyncHandler | undefined} */
this.leave = leave;
}
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Node | null}
*/
visit(node, parent, prop, index) {
if (node) {
if (this.enter) {
const _should_skip = this.should_skip;
const _should_remove = this.should_remove;
const _replacement = this.replacement;
this.should_skip = false;
this.should_remove = false;
this.replacement = null;
this.enter.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) this.remove(parent, prop, index);
const skipped = this.should_skip;
const removed = this.should_remove;
this.should_skip = _should_skip;
this.should_remove = _should_remove;
this.replacement = _replacement;
if (skipped) return node;
if (removed) return null;
}
/** @type {keyof Node} */
let key;
for (key in node) {
/** @type {unknown} */
const value = node[key];
if (value && typeof value === "object") {
if (Array.isArray(value)) {
const nodes = value;
for (let i = 0; i < nodes.length; i += 1) {
const item = nodes[i];
if (isNode$1(item)) {
if (!this.visit(item, node, key, i)) i--;
}
}
} else if (isNode$1(value)) this.visit(value, node, key, null);
}
}
if (this.leave) {
const _replacement = this.replacement;
const _should_remove = this.should_remove;
this.replacement = null;
this.should_remove = false;
this.leave.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) this.remove(parent, prop, index);
const removed = this.should_remove;
this.replacement = _replacement;
this.should_remove = _should_remove;
if (removed) return null;
}
}
return node;
}
};
/**
* Ducktype a node.
*
* @param {unknown} value
* @returns {value is Node}
*/
function isNode$1(value) {
return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string";
}
/**
* @typedef {import('estree').Node} Node
* @typedef {import('./sync.js').SyncHandler} SyncHandler
* @typedef {import('./async.js').AsyncHandler} AsyncHandler
*/
/**
* @param {Node} ast
* @param {{
* enter?: SyncHandler
* leave?: SyncHandler
* }} walker
* @returns {Node | null}
*/
function walk(ast, { enter, leave }) {
return new SyncWalker(enter, leave).visit(ast, null);
}
const TS_NODE_TYPES = [
"TSAsExpression",
"TSTypeAssertion",
"TSNonNullExpression",
"TSInstantiationExpression",
"TSSatisfiesExpression"
];
/**
* Walks the AST and applies the provided handlers.
*
* @template T - The type of the AST node.
* @param {T} node - The root node of the AST.
* @param {WalkHandlers<T, void>} hooks - The handlers to be applied during the walk.
* @returns {T | null} - The modified AST node or null if the node is removed.
*/
const walkAST = walk;
/**
* Modified from https://github.com/vuejs/core/blob/main/packages/compiler-core/src/babelUtils.ts
* To support browser environments and JSX.
*
* https://github.com/vuejs/core/blob/main/LICENSE
*/
/**
* Return value indicates whether the AST walked can be a constant
*/
function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {
const rootExp = root.type === "Program" ? root.body[0].type === "ExpressionStatement" && root.body[0].expression : root;
walkAST(root, {
enter(node, parent) {
parent && parentStack.push(parent);
if (parent && parent.type.startsWith("TS") && !TS_NODE_TYPES.includes(parent.type)) return this.skip();
if (isIdentifier(node)) {
const isLocal = !!knownIds[node.name];
const isRefed = isReferencedIdentifier(node, parent, parentStack);
if (includeAll || isRefed && !isLocal) onIdentifier(node, parent, parentStack, isRefed, isLocal);
} else if (node.type === "ObjectProperty" && parent?.type === "ObjectPattern") node.inPattern = true;
else if (isFunctionType(node))
/* v8 ignore if -- @preserve */
if (node.scopeIds) node.scopeIds.forEach((id) => markKnownIds(id, knownIds));
else walkFunctionParams(node, (id) => markScopeIdentifier(node, id, knownIds));
else if (node.type === "BlockStatement")
/* v8 ignore if -- @preserve */
if (node.scopeIds) node.scopeIds.forEach((id) => markKnownIds(id, knownIds));
else walkBlockDeclarations(node, (id) => markScopeIdentifier(node, id, knownIds));
else if (node.type === "CatchClause" && node.param) for (const id of extractIdentifiers(node.param)) markScopeIdentifier(node, id, knownIds);
else if (isForStatement(node)) walkForStatement(node, false, (id) => markScopeIdentifier(node, id, knownIds));
},
leave(node, parent) {
parent && parentStack.pop();
if (node !== rootExp && node.scopeIds) for (const id of node.scopeIds) {
knownIds[id]--;
if (knownIds[id] === 0) delete knownIds[id];
}
}
});
}
function walkFunctionParams(node, onIdent) {
for (const p of node.params) for (const id of extractIdentifiers(p)) onIdent(id);
}
function walkBlockDeclarations(block, onIdent) {
for (const stmt of block.body) if (stmt.type === "VariableDeclaration") {
if (stmt.declare) continue;
for (const decl of stmt.declarations) for (const id of extractIdentifiers(decl.id)) onIdent(id);
} else if (stmt.type === "FunctionDeclaration" || stmt.type === "ClassDeclaration") {
/* v8 ignore if -- @preserve */
if (stmt.declare || !stmt.id) continue;
onIdent(stmt.id);
} else if (isForStatement(stmt)) walkForStatement(stmt, true, onIdent);
}
function walkForStatement(stmt, isVar, onIdent) {
const variable = stmt.type === "ForStatement" ? stmt.init : stmt.left;
if (variable && variable.type === "VariableDeclaration" && (variable.kind === "var" ? isVar : !isVar)) for (const decl of variable.declarations) for (const id of extractIdentifiers(decl.id)) onIdent(id);
}
function markKnownIds(name, knownIds) {
if (name in knownIds) knownIds[name]++;
else knownIds[name] = 1;
}
function markScopeIdentifier(node, child, knownIds) {
const { name } = child;
/* v8 ignore if -- @preserve */
if (node.scopeIds && node.scopeIds.has(name)) return;
markKnownIds(name, knownIds);
(node.scopeIds || (node.scopeIds = /* @__PURE__ */ new Set())).add(name);
}
//#endregion
//#region src/core/helper/use-model.ts?raw
var use_model_default = "import { customRef, watchSyncEffect } from \"vue\";\nconst EMPTY_OBJ = {};\nexport function useModel(props, name, options = {}) {\n const res = customRef((track, trigger) => {\n let localValue = options && options.default;\n let prevSetValue = EMPTY_OBJ;\n watchSyncEffect(() => {\n let propValue = props[name];\n if (propValue === void 0) {\n propValue = options && options.default;\n }\n if (!Object.is(localValue, propValue)) {\n localValue = propValue;\n trigger();\n }\n });\n return {\n get() {\n track();\n return options.get ? options.get(localValue) : localValue;\n },\n set(value) {\n const emittedValue = options.set ? options.set(value) : value;\n if (Object.is(emittedValue, localValue) && (prevSetValue === EMPTY_OBJ || Object.is(value, prevSetValue)))\n return;\n localValue = emittedValue;\n trigger();\n for (const emit of [props[`onUpdate:${name}`]].flat()) {\n if (typeof emit === \"function\") emit(emittedValue);\n }\n prevSetValue = value;\n }\n };\n });\n res[Symbol.iterator] = () => {\n let i = 0;\n return {\n next() {\n if (i < 2) {\n return {\n value: i++ ? props[`${name}Modifiers`] || {} : res,\n done: false\n };\n } else {\n return { done: true };\n }\n }\n };\n };\n return res;\n}\n";
//#endregion
//#region src/core/helper/with-defaults.ts?raw
var with_defaults_default = "function resolveDefaultProps(paths) {\n const result = {};\n for (const path of Object.keys(paths)) {\n const segments = path.split(/[.?[\\]]/).filter(Boolean);\n let current = result;\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n if (i === segments.length - 1) {\n current[segment] = paths[path];\n } else {\n if (!current[segment]) {\n current[segment] = Number.isNaN(Number(segments[i + 1])) ? {} : [];\n }\n current = current[segment];\n }\n }\n }\n return result;\n}\nexport function createPropsDefaultProxy(props, defaults) {\n const defaultProps = resolveDefaultProps(defaults);\n const result = {};\n for (const key of /* @__PURE__ */ new Set([\n ...Object.keys(props),\n ...Object.keys(defaultProps)\n ])) {\n Object.defineProperty(result, key, {\n enumerable: true,\n get: () => props[key] === void 0 ? defaultProps[key] : props[key]\n });\n }\n return result;\n}\n";
//#endregion
//#region src/core/helper/index.ts
const helperPrefix = "/vue-jsx-vapor/macros";
const useModelHelperId = `${helperPrefix}/use-model`;
const withDefaultsHelperId = `${helperPrefix}/with-defaults`;
//#endregion
//#region src/core/utils.ts
function prependFunctionalNode(node, s, result) {
const isBlockStatement = node.body.type === "BlockStatement";
const start = node.body.extra?.parenthesized ? node.body.extra.parenStart : node.body.start;
s.appendRight(start + (isBlockStatement ? 1 : 0), `${result};${isBlockStatement ? "" : "return "}`);
if (!isBlockStatement) {
s.appendLeft(start, "{");
s.appendRight(node.end, "}");
}
}
function isFunctionalNode(node) {
return !!(node && (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression"));
}
function getParamsStart(node, code) {
return node.params[0] ? node.params[0].start : node.start + (code.slice(node.start, node.body.start).match(/\(\s*\)/)?.index || 0) + 1;
}
function getDefaultValue(node) {
if (node.type === "TSNonNullExpression") return getDefaultValue(node.expression);
if (node.type === "TSAsExpression") return getDefaultValue(node.expression);
return node;
}
let require$1;
function getRequire() {
if (require$1) return require$1;
try {
if (globalThis.process?.getBuiltinModule) {
const module$1 = process.getBuiltinModule("node:module");
if (module$1?.createRequire) return require$1 = module$1.createRequire(require("url").pathToFileURL(__filename).href);
}
} catch {}
}
const importedMap = /* @__PURE__ */ new WeakMap();
const HELPER_PREFIX = "__";
function importHelperFn(s, imported, local = imported, from = "vue") {
const cacheKey = `${from}@${imported}`;
if (!importedMap.get(s)?.has(cacheKey)) {
s.appendLeft(0, `\nimport ${imported === "default" ? HELPER_PREFIX + local : `{ ${imported} as ${HELPER_PREFIX + local} }`} from ${JSON.stringify(from)};`);
if (importedMap.has(s)) importedMap.get(s).add(cacheKey);
else importedMap.set(s, new Set([cacheKey]));
}
return `${HELPER_PREFIX}${local}`;
}
//#endregion
//#region src/core/restructure.ts
function restructure(s, node, options = {}) {
let index = 0;
const propList = [];
for (const param of node.params) {
const path = `${HELPER_PREFIX}props${index++ || ""}`;
const props = getProps(s, options, param, path);
if (props) {
s.overwrite(param.start, param.end, path);
propList.push(...props);
}
}
if (propList.length) {
const defaultValues = {};
const rests = [];
for (const prop of propList) {
if (prop.isRest) rests.push(prop);
if (prop.defaultValue) {
const paths = prop.path.split(/\.|\[/);
if (!options.skipDefaultProps || paths.length !== 1) (defaultValues[paths[0]] ??= []).push(prop);
}
}
for (const [index$1, rest] of rests.entries()) prependFunctionalNode(node, s, options.generateRestProps?.(rest.name, index$1, rests) ?? `\nconst ${rest.name} = ${importHelperFn(s, "createPropsRestProxy")}(${rest.path}, [${rest.value}])`);
for (const [path, values] of Object.entries(defaultValues)) prependFunctionalNode(node, s, `\n${path} = ${importHelperFn(s, "createPropsDefaultProxy", void 0, options.withDefaultsFrom ?? withDefaultsHelperId)}(${path}, {${values.map((i) => `'${i.path.replace(path, "")}${i.value}': ${i.defaultValue}`).join(", ")}})`);
walkIdentifiers(node.body, (id, parent) => {
const prop = propList.find((i) => i.name === id.name);
if (prop && !prop.isRest) s.overwrite(id.start, id.end, `${parent?.type === "ObjectProperty" && parent.shorthand ? `${id.name}: ` : ""}${prop.path}${prop.value}`);
}, false);
}
return propList;
}
function getProps(s, options, node, path = "", props = []) {
const properties = node.type === "ObjectPattern" ? node.properties : node.type === "ArrayPattern" ? node.elements : [];
if (!properties.length) return;
const propNames = [];
properties.forEach((prop, index) => {
if (prop?.type === "Identifier") {
props.push({
name: prop.name,
path,
value: `[${index}]`
});
propNames.push(`'${prop.name}'`);
} else if (prop?.type === "AssignmentPattern" && prop.left.type === "Identifier") {
const defaultValue = getDefaultValue(prop.right);
props.push({
path,
name: prop.left.name,
value: `[${index}]`,
defaultValue: s.slice(defaultValue.start, defaultValue.end)
});
propNames.push(`'${prop.left.name}'`);
} else if (prop?.type === "ObjectProperty" && prop.key.type === "Identifier") {
if (prop.value.type === "AssignmentPattern") if (prop.value.left.type === "Identifier") {
const defaultValue = getDefaultValue(prop.value.right);
props.push({
path,
name: prop.value.left.name,
value: `.${prop.key.name}`,
defaultValue: s.slice(defaultValue.start, defaultValue.end)
});
} else getProps(s, options, prop.value.left, `${path}.${prop.key.name}`, props);
else if (!getProps(s, options, prop.value, `${path}.${prop.key.name}`, props)) {
const name = prop.value.type === "Identifier" ? prop.value.name : prop.key.name;
props.push({
path,
name,
value: `.${prop.key.name}`
});
}
propNames.push(`'${prop.key.name}'`);
} else if (prop?.type === "RestElement" && prop.argument.type === "Identifier" && !prop.argument.name.startsWith(`${HELPER_PREFIX}props`)) props.push({
path,
name: prop.argument.name,
value: propNames.join(", "),
isRest: true
});
else if (prop) getProps(s, options, prop, `${path}[${index}]`, props);
});
return props.length ? props : void 0;
}
//#endregion
//#region src/core/define-component/await.ts
function transformAwait(root, s) {
if (root.body.type !== "BlockStatement") return;
let hasAwait = false;
for (const node of root.body.body) if (node.type === "VariableDeclaration" && !node.declare || node.type.endsWith("Statement")) {
const scope = [root.body.body];
walkAST(node, {
enter(child, parent) {
if (isFunctionType(child)) this.skip();
if (child.type === "BlockStatement") scope.push(child.body);
if (child.type === "AwaitExpression") {
hasAwait = true;
processAwait(s, child, !!scope.at(-1)?.some((n, i) => {
return (scope.length === 1 || i > 0) && n.type === "ExpressionStatement" && n.start === child.start;
}), parent.type === "ExpressionStatement");
}
},
leave(node$1) {
if (node$1.type === "BlockStatement") scope.pop();
}
});
}
if (hasAwait) s.prependLeft(root.body.start + 1, `\nlet __temp, __restore\n`);
}
function processAwait(s, node, needSemi, isStatement) {
const argumentStart = node.argument.extra && node.argument.extra.parenthesized ? node.argument.extra.parenStart : node.argument.start;
const argumentStr = s.slice(argumentStart, node.argument.end);
const containsNestedAwait = /\bawait\b/.test(argumentStr);
s.overwrite(node.start, argumentStart, `${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${importHelperFn(s, `withAsyncContext`)}(${containsNestedAwait ? `async ` : ``}() => `);
s.appendLeft(node.end, `)),\n ${isStatement ? `` : `__temp = `}await __temp,\n __restore()${isStatement ? `` : `,\n __temp`}\n)`);
}
//#endregion
//#region src/core/define-component/return.ts
function transformReturn(root, s) {
const node = root.body.type === "BlockStatement" ? root.body.body.find((node$1) => node$1.type === "ReturnStatement")?.argument : root.body;
if (!node || isFunctionalNode(node)) return;
s.appendRight(node.extra?.parenthesized ? node.extra.parenStart : node.start, "() => ");
}
//#endregion
//#region src/core/define-component/index.ts
function transformDefineComponent(root, propsName, macros, s, autoReturnFunction = false) {
if (!macros.defineComponent) return;
const defineComponentName = s.slice(macros.defineComponent.callee.start, macros.defineComponent.callee.end);
if (defineComponentName && !["defineComponent", "defineVaporComponent"].includes(defineComponentName)) importHelperFn(s, "defineComponent", defineComponentName);
let hasRestProp = false;
const props = {};
if (root.params[0]) {
if (root.params[0].type === "Identifier") {
getWalkedIds(root, propsName).forEach((id) => props[id] = null);
prependFunctionalNode(root, s, `const ${propsName} = ${importHelperFn(s, "useFullProps", void 0, "/vue-jsx-vapor/props")}()`);
s.overwrite(root.params[0].start, root.params[0].end, root.params.length > 1 ? `${HELPER_PREFIX}props` : root.start === root.params[0].start ? "()" : "");
} else if (root.params[0].type === "ObjectPattern") {
const restructuredProps = root.params[0];
for (const prop of restructuredProps.properties) {
if (prop.type !== "ObjectProperty" || prop.key.type !== "Identifier") continue;
const propName = prop.key.name;
if (prop.value.type !== "AssignmentPattern") {
props[propName] = null;
continue;
}
const defaultValue = getDefaultValue(prop.value.right);
let isRequired = false;
walkAST(prop.value.right, { enter(node) {
if (node.type === "TSNonNullExpression") {
isRequired = true;
this.skip();
}
} });
const propOptions = [];
if (isRequired) propOptions.push("required: true");
if (defaultValue) {
const { value, type, skipFactory } = getTypeAndValue(s, defaultValue);
if (type) propOptions.push(`type: ${type}`);
if (value) propOptions.push(`default: ${value}`);
if (skipFactory) propOptions.push("skipFactory: true");
}
if (propOptions.length) props[propName] = `{ ${propOptions.join(", ")} }`;
else props[propName] = null;
}
restructure(s, root, {
skipDefaultProps: true,
generateRestProps: (restPropsName, index, list) => {
if (index === list.length - 1) {
hasRestProp = true;
return `const ${restPropsName} = ${importHelperFn(s, "useAttrs")}()`;
}
}
});
}
}
transformDefineModel$1(s, macros.defineModel, props);
const propsString = Object.entries(props).map(([key, value]) => `'${key}': ${value}`).join(", \n");
if (propsString) {
const resolvedPropsString = `${hasRestProp ? "inheritAttrs: false, " : ""}props: {\n${propsString}\n}`;
const compOptions = macros.defineComponent.arguments[1];
if (!compOptions) s.appendRight(root.end, `, { ${resolvedPropsString} }`);
else if (compOptions.type === "ObjectExpression") {
s.appendLeft(compOptions.start, `{ ${resolvedPropsString}, ...`);
s.appendRight(compOptions.end, " }");
}
}
transformAwait(root, s);
if (autoReturnFunction) transformReturn(root, s);
}
function getWalkedIds(root, propsName) {
const walkedIds = /* @__PURE__ */ new Set();
walkIdentifiers(root.body, (id, parent) => {
if (id.name === propsName && (parent?.type === "MemberExpression" || parent?.type === "JSXMemberExpression" || parent?.type === "OptionalMemberExpression")) {
const prop = parent.property.type === "Identifier" || parent.property.type === "JSXIdentifier" ? parent.property.name : parent.property.type === "StringLiteral" ? parent.property.value : "";
if (prop) walkedIds.add(prop);
}
});
return walkedIds;
}
function transformDefineModel$1(s, defineModel, props) {
for (const { expression, isRequired } of defineModel || []) {
const modelOptions = expression.arguments[0]?.type === "ObjectExpression" ? expression.arguments[0] : expression.arguments[1]?.type === "ObjectExpression" ? expression.arguments[1] : void 0;
const options = {};
if (isRequired) options.required = true;
let defaultValueNode;
for (const prop of modelOptions?.properties || []) if (prop.type === "ObjectProperty" && prop.key.type === "Identifier" && [
"validator",
"type",
"required",
"default"
].includes(prop.key.name)) {
if (prop.key.name === "default") defaultValueNode = prop.value;
options[prop.key.name] = s.slice(prop.value.start, prop.value.end);
}
if (defaultValueNode && !options.type) {
const { value, type, skipFactory } = getTypeAndValue(s, defaultValueNode);
if (type) options.type = type;
if (value) options.default = value;
if (skipFactory) options.skipFactory = "true";
}
const propName = expression.arguments[0]?.type === "StringLiteral" ? expression.arguments[0].value : "modelValue";
props[propName] = Object.keys(options).length ? `{ ${Object.entries(options).map(([key, value]) => `${key}: ${value}`).join(", ")} }` : null;
props[`onUpdate:${propName}`] = null;
props[`${propName === "modelValue" ? "model" : propName}Modifiers`] = null;
}
}
function getTypeAndValue(s, node) {
let value = "";
let type = "";
let skipFactory = false;
switch (node.type) {
case "StringLiteral":
type = "String";
value = `'${node.value}'`;
break;
case "BooleanLiteral":
type = "Boolean";
value = String(node.value);
break;
case "NumericLiteral":
type = "Number";
value = String(node.value);
break;
case "ObjectExpression":
type = "Object";
value = `() => (${s.slice(node.start, node.end)})`;
break;
case "ArrayExpression":
type = "Array";
value = `() => (${s.slice(node.start, node.end)})`;
break;
default: if (isFunctionalNode(node)) {
type = "Function";
value = s.slice(node.start, node.end);
} else if (node.type === "Identifier") if (node.name === "undefined") value = "undefined";
else {
skipFactory = true;
value = s.slice(node.start, node.end);
}
else if (node.type === "NullLiteral") value = "null";
}
return {
value,
type,
skipFactory
};
}
//#endregion
//#region src/core/define-expose.ts
function transformDefineExpose(node, s) {
s.overwrite(node.callee.start, node.callee.end, ";");
s.appendRight(node.arguments[0]?.start || node.end - 1, `${importHelperFn(s, "getCurrentInstance", void 0, "/vue-jsx-vapor/props")}().exposed = `);
}
//#endregion
//#region src/core/define-model.ts
function transformDefineModel(node, propsName, s) {
s.overwrite(node.callee.start, node.callee.end, importHelperFn(s, "useModel", void 0, useModelHelperId));
s.appendRight(node.arguments[0]?.start || node.end - 1, `${propsName}, ${node.arguments[0]?.type === "StringLiteral" ? "" : `'modelValue',`}`);
}
//#endregion
//#region src/core/define-slots.ts
function transformDefineSlots(node, s) {
s.overwrite(node.start, node.arguments[0]?.start && node.arguments[0].start - 1 || node.typeArguments?.end || node.callee.end, `Object.assign`);
const slots = `${importHelperFn(s, "useSlots")}()`;
s.appendLeft(node.end - 1, `${node.arguments[0] ? "," : "{}, "}${slots}`);
}
//#endregion
//#region src/core/define-style.ts
function transformDefineStyle(defineStyle, index, root, s, importMap, { defineSlots }) {
const { expression, lang, isCssModules } = defineStyle;
if (expression.arguments[0]?.type !== "TemplateLiteral") return;
let css = s.slice(expression.arguments[0].start, expression.arguments[0].end).slice(1, -1);
const scopeId = (0, hash_sum.default)(css);
const vars = /* @__PURE__ */ new Map();
expression.arguments[0].expressions.forEach((exp) => {
const cssVar = s.slice(exp.start, exp.end);
const cssVarId = toCssVarId(cssVar, `--${scopeId}-`);
s.overwrite(exp.start - 2, exp.end + 1, `var(${cssVarId})`);
vars.set(cssVarId, cssVar);
});
let returnExpression = root && getReturnStatement(root);
if (isFunctionalNode(returnExpression)) returnExpression = getReturnStatement(returnExpression);
if (vars.size && returnExpression) {
const children = returnExpression.type === "JSXElement" ? [returnExpression] : returnExpression.type === "JSXFragment" ? returnExpression.children : [];
const varString = Array.from(vars.entries()).map(([key, value]) => `'${key}': ${value}`).join(", ");
for (const child of children) if (child.type === "JSXElement") s.appendRight(child.openingElement.name.end, ` {...{style:{${varString}}}}`);
}
let scoped = !!root;
if (expression.arguments[1]?.type === "ObjectExpression") {
for (const prop of expression.arguments[1].properties) if (prop.type === "ObjectProperty" && prop.key.type === "Identifier" && prop.key.name === "scoped" && prop.value.type === "BooleanLiteral") scoped = prop.value.value;
}
if (scoped && root) {
const slotNames = defineSlots?.id ? defineSlots.id.type === "Identifier" ? defineSlots.id.name : defineSlots.id.type === "ObjectPattern" ? defineSlots.id.properties.map((prop) => {
const value = prop.type === "RestElement" ? prop.argument : prop.value;
return s.slice(value.start, value.end);
}) : [] : [];
walkAST(root, { enter(node) {
if (node.type === "JSXElement" && s.slice(node.openingElement.name.start, node.openingElement.name.end) !== "template") {
let subfix = "";
if (slotNames.length) {
const tagName = node.openingElement.name.type === "JSXMemberExpression" ? node.openingElement.name.object : node.openingElement.name;
const name = s.slice(tagName.start, tagName.end);
subfix = slotNames.includes(name) ? "-s" : "";
}
s.appendRight(node.openingElement.name.end, ` data-v-${scopeId}${subfix}=""`);
}
} });
}
css = s.slice(expression.arguments[0].start, expression.arguments[0].end).slice(1, -1).replaceAll(/\/\/(.*)(?=\n)/g, "/*$1*/");
const importId = `${helperPrefix}/define-style/${index}?scopeId=${scopeId}&scoped=${scoped}&lang.${isCssModules ? "module." : ""}${lang}`;
importMap.set(importId, css);
s.appendLeft(0, isCssModules ? `import style${index} from "${importId}";` : `import "${importId}";`);
s.overwrite(expression.start, expression.end, isCssModules ? `style${index}` : "");
}
function getReturnStatement(root) {
if (root.body.type === "BlockStatement") {
const returnStatement = root.body.body.find((node) => node.type === "ReturnStatement");
if (returnStatement) return returnStatement.argument;
} else return root.body;
}
function toCssVarId(name, prefix = "") {
return prefix + name.replaceAll(/\W/g, (searchValue, replaceValue) => {
return searchValue === "." ? "-" : name.charCodeAt(replaceValue).toString();
});
}
//#endregion
//#region src/core/index.ts
let babelParse;
async function getBabelParse() {
if (babelParse) return babelParse;
const require$2 = getRequire();
try {
return babelParse = require$2 ? require$2("vue/compiler-sfc").babelParse : (await import("https://esm.sh/@vue/compiler-sfc")).babelParse;
} catch {}
}
async function transformJsxMacros(code, id, importMap, options) {
const s = new magic_string.default(code);
const lang = getLang(id);
if (lang === "dts") return;
const ast = (await getBabelParse())(s.original, {
sourceType: "module",
plugins: lang === "tsx" ? ["typescript", "jsx"] : lang === "jsx" ? ["jsx"] : lang === "ts" ? ["typescript"] : []
}).program;
const rootMap = getRootMap(ast, s, options);
let defineStyleIndex = 0;
for (const [root, macros] of rootMap) {
macros.defineStyle?.forEach((defineStyle) => {
transformDefineStyle(defineStyle, defineStyleIndex++, root, s, importMap, macros);
});
if (root === void 0) continue;
let propsName = `${HELPER_PREFIX}props`;
if (root.params[0]) {
if (root.params[0].type === "Identifier") propsName = root.params[0].name;
else if (root.params[0].type === "ObjectPattern") {
const lastProp = root.params[0].properties.at(-1);
if (!macros.defineComponent && lastProp?.type === "RestElement" && lastProp.argument.type === "Identifier") propsName = lastProp.argument.name;
else s.appendRight(root.params[0].extra?.trailingComma ? root.params[0].extra?.trailingComma + 1 : lastProp?.end || root.params[0].end - 1, `${!root.params[0].extra?.trailingComma && root.params[0].properties.length ? "," : ""} ...${HELPER_PREFIX}props`);
}
} else if (macros.defineModel?.length) s.appendRight(getParamsStart(root, s.original), propsName);
if (macros.defineComponent) transformDefineComponent(root, propsName, macros, s, options.defineComponent?.autoReturnFunction);
if (macros.defineModel?.length) macros.defineModel.forEach(({ expression }) => {
transformDefineModel(expression, propsName, s);
});
if (macros.defineSlots) transformDefineSlots(macros.defineSlots.expression, s);
if (macros.defineExpose) transformDefineExpose(macros.defineExpose, s);
}
if (s.hasChanged()) return {
code: s.toString(),
get map() {
return s.generateMap({
source: id,
includeContent: true,
hires: "boundary"
});
}
};
}
function getRootMap(ast, s, options) {
const parents = [];
const rootMap = /* @__PURE__ */ new Map();
walkAST(ast, {
enter(node, parent) {
parents.unshift(parent);
const root = isFunctionalNode(parents[1]) ? parents[1] : void 0;
if (root && parents[2]?.type === "CallExpression" && options.defineComponent.alias.includes(s.slice(parents[2].callee.start, parents[2].callee.end))) {
if (!rootMap.has(root)) rootMap.set(root, {});
if (!rootMap.get(root).defineComponent) rootMap.get(root).defineComponent = parents[2];
}
const expression = node.type === "VariableDeclaration" ? node.declarations[0].init?.type === "CallExpression" && s.slice(node.declarations[0].init.callee.start, node.declarations[0].init.callee.end) === "$" ? node.declarations[0].init.arguments[0] : node.declarations[0].init : node.type === "ExpressionStatement" ? node.expression : void 0;
if (!expression) return;
const macroExpression = getMacroExpression(expression, options);
if (!macroExpression) return;
if (!rootMap.has(root)) rootMap.set(root, {});
const macro = macroExpression.callee.type === "MemberExpression" ? macroExpression.callee.object : macroExpression.callee;
const macroName = s.slice(macro.start, macro.end);
if (macroName) {
if (options.defineModel.alias.includes(macroName)) (rootMap.get(root).defineModel ??= []).push({
expression: macroExpression,
isRequired: expression.type === "TSNonNullExpression"
});
else if (options.defineStyle.alias.includes(macroName)) {
const lang = macroExpression.callee.type === "MemberExpression" && macroExpression.callee.property.type === "Identifier" ? macroExpression.callee.property.name : "css";
(rootMap.get(root).defineStyle ??= []).push({
expression: macroExpression,
isCssModules: node.type === "VariableDeclaration",
lang
});
} else if (options.defineSlots.alias.includes(macroName)) rootMap.get(root).defineSlots = {
expression: macroExpression,
id: node.type === "VariableDeclaration" ? node.declarations[0].id : void 0
};
else if (options.defineExpose.alias.includes(macroName)) rootMap.get(root).defineExpose = macroExpression;
}
},
leave() {
parents.shift();
}
});
return rootMap;
}
function getMacroExpression(node, options) {
if (node.type === "TSNonNullExpression") node = node.expression;
if (node.type === "CallExpression") {
if (node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "defineStyle") return node;
else if (node.callee.type === "Identifier" && [
...options.defineComponent.alias,
...options.defineSlots.alias,
...options.defineModel.alias,
...options.defineExpose.alias,
...options.defineStyle.alias
].includes(node.callee.name)) return node;
}
}
//#endregion
Object.defineProperty(exports, '__toESM', {
enumerable: true,
get: function () {
return __toESM;
}
});
Object.defineProperty(exports, 'getMacroExpression', {
enumerable: true,
get: function () {
return getMacroExpression;
}
});
Object.defineProperty(exports, 'getRequire', {
enumerable: true,
get: function () {
return getRequire;
}
});
Object.defineProperty(exports, 'isFunctionalNode', {
enumerable: true,
get: function () {
return isFunctionalNode;
}
});
Object.defineProperty(exports, 'restructure', {
enumerable: true,
get: function () {
return restructure;
}
});
Object.defineProperty(exports, 'transformJsxMacros', {
enumerable: true,
get: function () {
return transformJsxMacros;
}
});
Object.defineProperty(exports, 'useModelHelperId', {
enumerable: true,
get: function () {
return useModelHelperId;
}
});
Object.defineProperty(exports, 'use_model_default', {
enumerable: true,
get: function () {
return use_model_default;
}
});
Object.defineProperty(exports, 'withDefaultsHelperId', {
enumerable: true,
get: function () {
return withDefaultsHelperId;
}
});
Object.defineProperty(exports, 'with_defaults_default', {
enumerable: true,
get: function () {
return with_defaults_default;
}
});