65 lines
2.2 KiB
JavaScript
65 lines
2.2 KiB
JavaScript
const { parse, compile: compilerDomCompile } = require('@vue/compiler-dom');
|
|
|
|
const COMMENT_NODE_TYPE = 3;
|
|
|
|
const getPropIndex = (node, prop) => node.props?.findIndex((p) => p.name === prop) ?? -1;
|
|
|
|
function modifyKeysInsideTemplateTag(templateNode) {
|
|
let keyCandidate = null;
|
|
for (const node of templateNode.children) {
|
|
const keyBindingIndex = node.props
|
|
? node.props.findIndex((prop) => prop.arg && prop.arg.content === 'key')
|
|
: -1;
|
|
|
|
if (keyBindingIndex !== -1 && getPropIndex(node, 'for') === -1) {
|
|
if (!keyCandidate) {
|
|
keyCandidate = node.props[keyBindingIndex];
|
|
}
|
|
node.props.splice(keyBindingIndex, 1);
|
|
}
|
|
}
|
|
|
|
if (keyCandidate) {
|
|
templateNode.props.push(keyCandidate);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
parse,
|
|
compile(template, options) {
|
|
const rootNode = parse(template, options);
|
|
|
|
// We do not want to switch to whitespace: collapse mode which is Vue.js 3 default
|
|
// It will be too devastating to codebase
|
|
|
|
// However, without `whitespace: condense` Vue will treat spaces between comments
|
|
// and nodes itself as text nodes, resulting in multi-root component
|
|
// For multi-root component passing classes / attributes fallthrough will not work
|
|
|
|
// See https://github.com/vuejs/core/issues/7909 for details
|
|
|
|
// To fix that we simply drop all component comments only on top-level
|
|
rootNode.children = rootNode.children.filter((n) => n.type !== COMMENT_NODE_TYPE);
|
|
|
|
const pendingNodes = [rootNode];
|
|
while (pendingNodes.length) {
|
|
const currentNode = pendingNodes.pop();
|
|
if (getPropIndex(currentNode, 'for') !== -1) {
|
|
if (currentNode.tag === 'template') {
|
|
// This one will be dropped all together with compiler when we drop Vue.js 2 support
|
|
modifyKeysInsideTemplateTag(currentNode);
|
|
}
|
|
|
|
// This one will be dropped when https://github.com/vuejs/core/issues/7725 will be fixed
|
|
const vOncePropIndex = getPropIndex(currentNode, 'once');
|
|
if (vOncePropIndex !== -1) {
|
|
currentNode.props.splice(vOncePropIndex, 1);
|
|
}
|
|
}
|
|
|
|
currentNode.children?.forEach((child) => pendingNodes.push(child));
|
|
}
|
|
|
|
return compilerDomCompile(rootNode, options);
|
|
},
|
|
};
|