// src/core/utils.ts
function getChildrenLocation(node) {
if (node.children.length > 0) {
const lastChild = node.children[node.children.length - 1];
return [node.children[0].loc.start.offset, lastChild.loc.end.offset];
} else {
return void 0;
}
}
function parseVueRequest(id) {
const [filename, rawQuery] = id.split(`?`, 2);
const query = Object.fromEntries(new URLSearchParams(rawQuery));
if (query.vue != null) {
query.vue = true;
}
if (query.index != null) {
query.index = Number(query.index);
}
if (query.raw != null) {
query.raw = true;
}
if (query.url != null) {
query.url = true;
}
if (query.scoped != null) {
query.scoped = true;
}
return {
filename,
query
};
}
// src/core/constants.ts
var QUERY_NAMED_TEMPLATE = "?vue&type=named-template";
var QUERY_TEMPLATE = "type=template&namedTemplate";
var QUERY_TEMPLATE_MAIN = `${QUERY_TEMPLATE}&mainTemplate`;
var MAIN_TEMPLATE = Symbol();
// src/core/index.ts
import {
HELPER_PREFIX,
MagicString,
babelParse,
getLang,
getTransformResult,
importHelperFn,
isCallOf,
walkAST
} from "@vue-macros/common";
import { createTransformContext, parse, traverseNode } from "@vue/compiler-dom";
function transformTemplateIs(s) {
return (node) => {
if (!(node.type === 1 && node.tag === "template"))
return;
const propIs = node.props.find(
(prop) => prop.type === 6 && prop.name === "is"
);
if (!(propIs == null ? void 0 : propIs.value))
return;
const refName = propIs.value.content;
s.overwrite(
node.loc.start.offset,
node.loc.end.offset,
``
);
};
}
function preTransform(code, id, templateContent) {
const root = parse(code);
const templates = root.children.filter(
(node) => node.type === 1 && node.tag === "template"
);
if (templates.length <= 1)
return;
const s = new MagicString(code);
for (const node of templates) {
const propName = node.props.find(
(prop) => prop.type === 6 && prop.name === "name"
);
if (!propName) {
preTransformMainTemplate({ s, root, node, id, templateContent });
continue;
} else if (!propName.value) {
continue;
}
const name = propName.value.content;
let template = "";
const templateLoc = getChildrenLocation(node);
if (templateLoc) {
template = s.slice(...templateLoc);
}
if (!templateContent[id])
templateContent[id] = {};
templateContent[id][name] = template;
s.appendLeft(node.loc.start.offset, ``);
s.appendLeft(node.loc.end.offset, "");
}
return getTransformResult(s, id);
}
function preTransformMainTemplate({
s,
root,
node,
id,
templateContent
}) {
const ctx = createTransformContext(root, {
filename: id,
nodeTransforms: [transformTemplateIs(s)]
});
traverseNode(node, ctx);
const loc = getChildrenLocation(node);
if (!loc)
return;
if (!templateContent[id])
templateContent[id] = {};
templateContent[id][MAIN_TEMPLATE] = s.slice(...loc);
s.remove(...loc);
const offset = node.loc.start.offset + 1 + node.tag.length;
s.appendLeft(offset, ` src="${`${id}?vue&${QUERY_TEMPLATE_MAIN}`}"`);
}
function postTransform(code, id, customBlocks) {
var _a, _b, _c;
const lang = getLang(id);
const program = babelParse(code, lang);
const { filename } = parseVueRequest(id);
if (!id.includes(QUERY_TEMPLATE_MAIN)) {
postTransformMainEntry(program, filename, customBlocks);
return;
}
const s = new MagicString(code);
const subTemplates = [];
for (const node of program.body) {
if (node.type === "ExportNamedDeclaration" && ((_a = node.declaration) == null ? void 0 : _a.type) === "FunctionDeclaration" && ((_b = node.declaration.id) == null ? void 0 : _b.name) === "render") {
const params = node.declaration.params;
if (params.length > 0) {
const lastParams = params[node.declaration.params.length - 1];
const loc = [params[0].start, lastParams.end];
const paramsText = s.slice(...loc);
s.overwrite(...loc, "...args");
s.appendLeft(
node.declaration.body.start + 1,
`
let [${paramsText}] = args`
);
}
}
}
walkAST(program, {
enter(node) {
if (isCallOf(node, ["_createVNode", "_createBlock"]) && isCallOf(node.arguments[0], "_resolveDynamicComponent") && node.arguments[0].arguments[0].type === "StringLiteral" && node.arguments[0].arguments[0].value.startsWith("named-template-")) {
subTemplates.push({
vnode: node,
component: node.arguments[0],
name: node.arguments[0].arguments[0].value.replace(
"named-template-",
""
),
fnName: node.callee.name
});
}
}
});
if (subTemplates.length === 0)
return;
for (const { vnode, component, name, fnName } of subTemplates) {
const block = (_c = customBlocks[filename]) == null ? void 0 : _c[name];
if (!block)
throw new SyntaxError(`Unknown named template: ${name}`);
const render = `${HELPER_PREFIX}block_${escapeTemplateName(
name
)}.render(...args)`;
if (fnName === "_createVNode") {
s.overwriteNode(vnode, render);
} else if (fnName === "_createBlock") {
importHelperFn(s, 0, "Fragment", "vue");
s.overwriteNode(component, `${HELPER_PREFIX}Fragment`);
const text = `${vnode.arguments[1] ? "" : ", null"}, [${render}]`;
s.appendLeft((vnode.arguments[1] || vnode.arguments[0]).end, text);
}
}
for (const [name, source] of Object.entries(customBlocks[filename])) {
s.prepend(
`import { default as ${HELPER_PREFIX}block_${escapeTemplateName(
name
)} } from ${JSON.stringify(source)}
`
);
}
return getTransformResult(s, id);
}
function postTransformMainEntry(program, id, customBlocks) {
for (const node of program.body) {
if (node.type === "ImportDeclaration" && node.source.value.includes(QUERY_NAMED_TEMPLATE)) {
const { name } = parseVueRequest(node.source.value).query;
if (!customBlocks[id])
customBlocks[id] = {};
customBlocks[id][name] = node.source.value;
}
}
}
function escapeTemplateName(name) {
return name.replace(/-/g, "$DASH");
}
export {
getChildrenLocation,
parseVueRequest,
QUERY_NAMED_TEMPLATE,
QUERY_TEMPLATE,
QUERY_TEMPLATE_MAIN,
MAIN_TEMPLATE,
transformTemplateIs,
preTransform,
preTransformMainTemplate,
postTransform,
postTransformMainEntry
};