更新
This commit is contained in:
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformAttr: NodeTransform;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformAttr = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const transformAttr = (node, _) => {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return;
|
||||
}
|
||||
node.props.forEach((prop) => {
|
||||
if ((0, uni_cli_shared_1.isAttributeNode)(prop) && prop.value) {
|
||||
switch (prop.name) {
|
||||
case 'style':
|
||||
prop.value.content = (0, shared_1.stringifyStyle)((0, shared_1.parseStringStyle)(prop.value.content)).slice(0, -1); // 移除最后一个分号,省点大小吧
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.transformAttr = transformAttr;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function isClassBinding({ arg }: DirectiveNode): boolean | undefined;
|
||||
export declare function findStaticClassIndex(props: (AttributeNode | DirectiveNode)[]): number;
|
||||
export declare function rewriteClass(index: number, classBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext): void;
|
||||
export declare function createVirtualHostClass(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;
|
||||
Generated
Vendored
+182
@@ -0,0 +1,182 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVirtualHostClass = exports.rewriteClass = exports.findStaticClassIndex = exports.isClassBinding = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const utils_1 = require("./utils");
|
||||
function isClassBinding({ arg }) {
|
||||
return (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'class');
|
||||
}
|
||||
exports.isClassBinding = isClassBinding;
|
||||
function findStaticClassIndex(props) {
|
||||
return props.findIndex((prop) => prop.name === 'class');
|
||||
}
|
||||
exports.findStaticClassIndex = findStaticClassIndex;
|
||||
function rewriteClass(index, classBindingProp, props, virtualHost, context) {
|
||||
const expr = classBindingProp.exp
|
||||
? (0, ast_1.parseExpr)(classBindingProp.exp, context)
|
||||
: undefined;
|
||||
let classBindingExpr;
|
||||
if (expr) {
|
||||
classBindingExpr = expr;
|
||||
if ((0, types_1.isObjectExpression)(expr)) {
|
||||
classBindingExpr = createClassBindingByObjectExpression(rewriteClassObjectExpression(expr, classBindingProp.loc, context));
|
||||
}
|
||||
else if ((0, types_1.isArrayExpression)(expr)) {
|
||||
classBindingExpr = createClassBindingByArrayExpression(rewriteClassArrayExpression(expr, context));
|
||||
}
|
||||
else {
|
||||
classBindingExpr = (0, ast_1.parseExpr)(rewriteClassExpression(classBindingProp.exp, context).content, context);
|
||||
}
|
||||
}
|
||||
else if (virtualHost) {
|
||||
classBindingExpr = (0, types_1.arrayExpression)([]);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
const staticClassPropIndex = findStaticClassIndex(props);
|
||||
if (staticClassPropIndex > -1) {
|
||||
const staticClass = props[staticClassPropIndex].value
|
||||
.content;
|
||||
if (staticClass) {
|
||||
if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
|
||||
classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
|
||||
}
|
||||
const staticClassLiterals = parseStaticClass(staticClass);
|
||||
if (index > staticClassPropIndex) {
|
||||
classBindingExpr.elements.unshift(...staticClassLiterals);
|
||||
}
|
||||
else {
|
||||
classBindingExpr.elements.push(...staticClassLiterals);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (virtualHost) {
|
||||
if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
|
||||
classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
|
||||
}
|
||||
classBindingExpr.elements.push((0, types_1.identifier)(uni_shared_1.VIRTUAL_HOST_CLASS));
|
||||
}
|
||||
if (!context.miniProgram.class.array) {
|
||||
classBindingExpr = parseClassBindingArrayExpr(classBindingExpr);
|
||||
}
|
||||
classBindingProp.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(classBindingExpr));
|
||||
}
|
||||
exports.rewriteClass = rewriteClass;
|
||||
function createVirtualHostClass(props, context) {
|
||||
const classBindingProp = (0, uni_cli_shared_1.createBindDirectiveNode)('class', '');
|
||||
delete classBindingProp.exp;
|
||||
rewriteClass(0, classBindingProp, props, true, context);
|
||||
return classBindingProp;
|
||||
}
|
||||
exports.createVirtualHostClass = createVirtualHostClass;
|
||||
/**
|
||||
* 目前 mp-toutiao, mp-alipay, mp-lark 不支持数组绑定class,故统一转换为字符串相加
|
||||
* @param classBindingExpr
|
||||
* @returns
|
||||
*/
|
||||
function parseClassBindingArrayExpr(classBindingExpr) {
|
||||
if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
|
||||
return classBindingExpr;
|
||||
}
|
||||
let binaryExpr;
|
||||
classBindingExpr.elements.forEach((expr) => {
|
||||
if ((0, types_1.isArrayExpression)(expr)) {
|
||||
expr = parseClassBindingArrayExpr(expr);
|
||||
}
|
||||
if (!binaryExpr) {
|
||||
binaryExpr = (0, types_1.parenthesizedExpression)(expr);
|
||||
}
|
||||
else {
|
||||
binaryExpr = (0, types_1.binaryExpression)('+', (0, types_1.binaryExpression)('+', binaryExpr, (0, types_1.stringLiteral)(' ')), expr);
|
||||
}
|
||||
});
|
||||
return binaryExpr;
|
||||
}
|
||||
function parseStaticClass(staticClass) {
|
||||
// 已经在 parse 阶段格式化了多余空格等
|
||||
return staticClass.split(' ').map((clazz) => (0, types_1.stringLiteral)(clazz));
|
||||
}
|
||||
function rewriteClassExpression(expr, context) {
|
||||
return (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.NORMALIZE_CLASS) + '(',
|
||||
expr,
|
||||
')',
|
||||
]), context);
|
||||
}
|
||||
function rewriteClassArrayExpression(expr, context) {
|
||||
expr.elements.forEach((prop, index) => {
|
||||
if (!(0, types_1.isStringLiteral)(prop)) {
|
||||
const code = (0, codegen_1.genBabelExpr)((0, types_1.arrayExpression)([(0, types_1.isSpreadElement)(prop) ? prop.argument : prop]));
|
||||
expr.elements[index] = (0, types_1.identifier)(rewriteClassExpression((0, compiler_core_1.createSimpleExpression)(code.slice(1, -1), false), context).content);
|
||||
}
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
function rewriteClassObjectExpression(expr, loc, context) {
|
||||
expr.properties.forEach((prop, index) => {
|
||||
if ((0, types_1.isSpreadElement)(prop)) {
|
||||
// <view :class="{...obj}"/>
|
||||
// <view class="{{[a]}}"/>
|
||||
const newExpr = (0, utils_1.rewriteSpreadElement)(runtimeHelpers_1.NORMALIZE_CLASS, prop, loc, context);
|
||||
if (newExpr) {
|
||||
expr.properties[index] = (0, types_1.objectProperty)(newExpr, (0, types_1.booleanLiteral)(true), true);
|
||||
}
|
||||
}
|
||||
else if ((0, types_1.isObjectProperty)(prop)) {
|
||||
const { key, value, computed } = prop;
|
||||
if (computed) {
|
||||
// {[handle(computedKey)]:1} => {[a]:1}
|
||||
prop.key = (0, utils_1.parseExprWithRewrite)((0, codegen_1.genBabelExpr)(key), loc, context, key);
|
||||
}
|
||||
if ((0, utils_1.isStaticLiteral)(value)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
const newExpr = (0, utils_1.parseExprWithRewriteClass)((0, codegen_1.genBabelExpr)(value), loc, context, value);
|
||||
if (newExpr) {
|
||||
prop.value = newExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
function createClassBindingByArrayExpression(expr) {
|
||||
const elements = [];
|
||||
expr.elements.forEach((prop) => {
|
||||
if ((0, types_1.isStringLiteral)(prop) || (0, types_1.isIdentifier)(prop)) {
|
||||
elements.push(prop);
|
||||
}
|
||||
});
|
||||
return (0, types_1.arrayExpression)(elements);
|
||||
}
|
||||
function createClassBindingByObjectExpression(expr) {
|
||||
const elements = [];
|
||||
expr.properties.forEach((prop) => {
|
||||
if ((0, types_1.isObjectProperty)(prop)) {
|
||||
const { value } = prop;
|
||||
if ((0, ast_1.isUndefined)(value) || (0, types_1.isPrivateName)(prop.key)) {
|
||||
// remove {a:undefined}
|
||||
return;
|
||||
}
|
||||
if ((0, types_1.isLiteral)(value)) {
|
||||
// {a:true,b:1,c:0} => ['a','b']
|
||||
if ((0, ast_1.isTrueExpr)(value)) {
|
||||
elements.push(prop.computed
|
||||
? prop.key
|
||||
: (0, ast_1.parseStringLiteral)(prop.key));
|
||||
}
|
||||
return;
|
||||
}
|
||||
elements.push((0, types_1.logicalExpression)('&&', value, prop.computed ? prop.key : (0, ast_1.parseStringLiteral)(prop.key)));
|
||||
}
|
||||
});
|
||||
return (0, types_1.arrayExpression)(elements);
|
||||
}
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
import { type ComponentNode, type DirectiveNode, type ElementNode } from '@vue/compiler-core';
|
||||
import { type NodeTransform, type TransformContext } from '../transform';
|
||||
export declare const transformComponent: NodeTransform;
|
||||
/**
|
||||
* 重写组件 props 绑定
|
||||
* @param node
|
||||
* @param context
|
||||
*/
|
||||
export declare function rewriteBinding({ tag, props }: ComponentNode, context: TransformContext): void;
|
||||
export declare function isPropsBinding({ arg }: DirectiveNode): boolean | undefined;
|
||||
export declare function rewritePropsBinding(dir: DirectiveNode, node: ElementNode, context: TransformContext): void;
|
||||
Generated
Vendored
+228
@@ -0,0 +1,228 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.rewritePropsBinding = exports.isPropsBinding = exports.rewriteBinding = exports.transformComponent = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const transform_1 = require("../transform");
|
||||
const utils_1 = require("./utils");
|
||||
const codegen_1 = require("../codegen");
|
||||
const types_1 = require("@babel/types");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const ast_1 = require("../ast");
|
||||
const vIf_1 = require("./vIf");
|
||||
const transformComponent = (node, context) => {
|
||||
if (!(0, uni_cli_shared_1.isUserComponent)(node, context)) {
|
||||
return;
|
||||
}
|
||||
// 新版本的 vue,识别 template 有差异,可能认为是自定义组件
|
||||
if (node.tag === 'template') {
|
||||
return;
|
||||
}
|
||||
addComponentType(node, context);
|
||||
addVueId(node, context);
|
||||
processBooleanAttr(node);
|
||||
return function postTransformComponent() {
|
||||
context.vueIds.pop();
|
||||
};
|
||||
};
|
||||
exports.transformComponent = transformComponent;
|
||||
function addComponentType(node, context) {
|
||||
if (!context.isMiniProgramComponent(node.tag)) {
|
||||
return;
|
||||
}
|
||||
node.props.push((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_COM_TYPE, 'm'));
|
||||
}
|
||||
function addVueId(node, context) {
|
||||
let { hashId, scopes, currentScope, currentVueId } = context;
|
||||
if (!hashId) {
|
||||
return;
|
||||
}
|
||||
let vueId = hashId + '-' + scopes.vueId++;
|
||||
const indexs = [];
|
||||
while (currentScope) {
|
||||
if ((0, transform_1.isVForScope)(currentScope)) {
|
||||
indexs.push(`+'-'+${currentScope.indexAlias}`);
|
||||
}
|
||||
currentScope = currentScope.parent;
|
||||
}
|
||||
const inFor = !!indexs.length;
|
||||
if (inFor) {
|
||||
vueId = `'${vueId}'` + indexs.reverse().join('');
|
||||
}
|
||||
context.vueIds.push(vueId);
|
||||
let value = vueId;
|
||||
if (currentVueId) {
|
||||
const isParentDynamic = currentVueId.includes('+');
|
||||
const isCurrentDynamic = vueId.includes('+');
|
||||
if (isParentDynamic || isCurrentDynamic) {
|
||||
value = `(${vueId})+','+(${isParentDynamic ? currentVueId : `'${currentVueId}'`})`;
|
||||
}
|
||||
else {
|
||||
value = vueId + ',' + currentVueId;
|
||||
}
|
||||
}
|
||||
if (value.includes('+')) {
|
||||
return node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_ID, value));
|
||||
}
|
||||
return node.props.push((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_VUE_ID, value));
|
||||
}
|
||||
/**
|
||||
* <uni-collapse accordion/> => <uni-collapse :accordion="true"/>
|
||||
* 否则部分平台(快手)可能获取到的 accordion 是空字符串
|
||||
* @param param0
|
||||
*/
|
||||
function processBooleanAttr({ props }) {
|
||||
props.forEach((prop, index) => {
|
||||
if (prop.type === compiler_core_1.NodeTypes.ATTRIBUTE &&
|
||||
typeof prop.value === 'undefined') {
|
||||
props.splice(index, 1, (0, uni_cli_shared_1.createBindDirectiveNode)(prop.name, 'true'));
|
||||
}
|
||||
});
|
||||
}
|
||||
const builtInProps = [
|
||||
// 'id',
|
||||
'class',
|
||||
'style',
|
||||
utils_1.ATTR_VUE_ID,
|
||||
utils_1.ATTR_VUE_PROPS,
|
||||
utils_1.ATTR_VUE_SLOTS,
|
||||
utils_1.ATTR_VUE_REF,
|
||||
utils_1.ATTR_VUE_REF_IN_FOR,
|
||||
utils_1.ATTR_COM_TYPE,
|
||||
utils_1.ATTR_ELEMENT_ID,
|
||||
utils_1.ATTR_SET_ELEMENT_STYLE,
|
||||
utils_1.ATTR_SET_ELEMENT_ANIMATION,
|
||||
'eO',
|
||||
'e-o',
|
||||
'onVI',
|
||||
'ref',
|
||||
'slot',
|
||||
'key',
|
||||
'is',
|
||||
];
|
||||
function isComponentProp(name) {
|
||||
if (builtInProps.includes(name)) {
|
||||
return false;
|
||||
}
|
||||
if (name.startsWith('data-')) {
|
||||
return false;
|
||||
}
|
||||
if (name === (0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_STYLE)) {
|
||||
return false;
|
||||
}
|
||||
if (name === (0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_ANIMATION)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* 重写组件 props 绑定
|
||||
* @param node
|
||||
* @param context
|
||||
*/
|
||||
function rewriteBinding({ tag, props }, context) {
|
||||
const isMiniProgramComponent = context.isMiniProgramComponent(tag);
|
||||
if (isMiniProgramComponent === 'plugin' ||
|
||||
isMiniProgramComponent === 'dynamicLib' ||
|
||||
isMiniProgramComponent === 'xr-frame' ||
|
||||
isMiniProgramComponent === 'ext' ||
|
||||
isMiniProgramComponent === 'weui') {
|
||||
// 因无法介入插件类型组件内部实现,故保留原始属性
|
||||
return;
|
||||
}
|
||||
const createObjectProperty = isMiniProgramComponent
|
||||
? (name, value) => (0, types_1.objectProperty)((0, types_1.identifier)((0, shared_1.camelize)(name)), value)
|
||||
: (name, value) => {
|
||||
const computed = !(0, compiler_core_1.isSimpleIdentifier)(name);
|
||||
return (0, types_1.objectProperty)(computed ? (0, types_1.stringLiteral)(name) : (0, types_1.identifier)(name), value, computed);
|
||||
};
|
||||
const properties = [];
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i];
|
||||
let isIdProp = false;
|
||||
if ((0, uni_cli_shared_1.isAttributeNode)(prop)) {
|
||||
const { name } = prop;
|
||||
isIdProp = name === 'id';
|
||||
if (!isComponentProp(name)) {
|
||||
continue;
|
||||
}
|
||||
properties.push(createObjectProperty(name, (0, types_1.stringLiteral)(prop.value?.content || '')));
|
||||
}
|
||||
else if ((0, uni_cli_shared_1.isDirectiveNode)(prop)) {
|
||||
if (prop.name !== 'bind') {
|
||||
continue;
|
||||
}
|
||||
const { arg, exp } = prop;
|
||||
if (!exp) {
|
||||
continue;
|
||||
}
|
||||
if (!arg) {
|
||||
const spreadElement = createVBindSpreadElement(prop, context);
|
||||
if (spreadElement) {
|
||||
properties.push(spreadElement);
|
||||
}
|
||||
}
|
||||
else if ((0, compiler_core_1.isStaticExp)(arg)) {
|
||||
isIdProp = arg.content === 'id';
|
||||
if (!isComponentProp(arg.content)) {
|
||||
continue;
|
||||
}
|
||||
// :name="name"
|
||||
const valueExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
|
||||
if (!valueExpr) {
|
||||
continue;
|
||||
}
|
||||
properties.push(createObjectProperty(arg.content, valueExpr));
|
||||
}
|
||||
else {
|
||||
// :[dynamic]="dynamic"
|
||||
const leftExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(arg), context, exp);
|
||||
if (!leftExpr) {
|
||||
continue;
|
||||
}
|
||||
const valueExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
|
||||
if (!valueExpr) {
|
||||
continue;
|
||||
}
|
||||
properties.push((0, types_1.objectProperty)((0, types_1.logicalExpression)('||', leftExpr, (0, types_1.stringLiteral)('')), valueExpr, true));
|
||||
}
|
||||
}
|
||||
// 即保留 id 属性,又补充到 props 中
|
||||
if (!isIdProp) {
|
||||
props.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (properties.length) {
|
||||
props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_PROPS, (0, codegen_1.genBabelExpr)((0, types_1.objectExpression)(properties))));
|
||||
}
|
||||
}
|
||||
exports.rewriteBinding = rewriteBinding;
|
||||
function createVBindSpreadElement(prop, context) {
|
||||
const { arg, exp } = prop;
|
||||
if (!exp) {
|
||||
return;
|
||||
}
|
||||
if (!arg) {
|
||||
const argument = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
|
||||
if (!argument) {
|
||||
return;
|
||||
}
|
||||
return (0, types_1.spreadElement)(argument);
|
||||
}
|
||||
}
|
||||
function isPropsBinding({ arg }) {
|
||||
return (arg &&
|
||||
arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
arg.content === utils_1.ATTR_VUE_PROPS);
|
||||
}
|
||||
exports.isPropsBinding = isPropsBinding;
|
||||
function rewritePropsBinding(dir, node, context) {
|
||||
dir.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)((0, utils_1.rewirteWithHelper)(runtimeHelpers_1.RENDER_PROPS, (0, ast_1.parseExpr)(dir.exp, context), dir.loc, context)) +
|
||||
(((0, vIf_1.isIfElementNode)(node) && node.vIf.name === 'else') ||
|
||||
context.miniProgram.component?.getPropertySync
|
||||
? `||''`
|
||||
: ''));
|
||||
}
|
||||
exports.rewritePropsBinding = rewritePropsBinding;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import { type ElementNode, type Property, type TemplateLiteral } from '@vue/compiler-core';
|
||||
import { type NodeTransform, type TransformContext } from '../transform';
|
||||
export interface DirectiveTransformResult {
|
||||
props: Property[];
|
||||
needRuntime?: boolean | symbol;
|
||||
ssrTagParts?: TemplateLiteral['elements'];
|
||||
}
|
||||
export declare const transformElement: NodeTransform;
|
||||
export declare function processProps(node: ElementNode, context: TransformContext, props?: ElementNode['props']): void;
|
||||
Generated
Vendored
+200
@@ -0,0 +1,200 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processProps = exports.transformElement = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const errors_1 = require("../errors");
|
||||
const vModel_1 = require("./vModel");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const transformElement = (node, context) => {
|
||||
return function postTransformElement() {
|
||||
node = context.currentNode;
|
||||
if (!(node.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
(node.tagType === compiler_core_1.ElementTypes.ELEMENT ||
|
||||
node.tagType === compiler_core_1.ElementTypes.COMPONENT))) {
|
||||
return;
|
||||
}
|
||||
if (node.tagType === compiler_core_1.ElementTypes.COMPONENT) {
|
||||
processComponent(node, context);
|
||||
}
|
||||
if (context.scopeId) {
|
||||
addScopeId(node, context.scopeId);
|
||||
}
|
||||
const { props } = node;
|
||||
if (props.length > 0) {
|
||||
processProps(node, context);
|
||||
}
|
||||
};
|
||||
};
|
||||
exports.transformElement = transformElement;
|
||||
function addScopeId(node, scopeId) {
|
||||
return (0, uni_cli_shared_1.addStaticClass)(node, scopeId);
|
||||
}
|
||||
function processComponent(node, context) {
|
||||
const { tag } = node;
|
||||
if (context.bindingComponents[tag]) {
|
||||
return;
|
||||
}
|
||||
// 1. dynamic component
|
||||
if ((0, uni_shared_1.isComponentTag)(tag)) {
|
||||
return context.onError((0, errors_1.createMPCompilerError)(8 /* MPErrorCodes.X_DYNAMIC_COMPONENT_NOT_SUPPORTED */, node.loc));
|
||||
}
|
||||
if ((0, compiler_core_1.findDir)(node, 'is')) {
|
||||
return context.onError((0, errors_1.createMPCompilerError)(6 /* MPErrorCodes.X_V_IS_NOT_SUPPORTED */, node.loc));
|
||||
}
|
||||
// TODO not supported
|
||||
// const isProp = findProp(node, 'is')
|
||||
// if (isProp) {
|
||||
// }
|
||||
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
|
||||
const builtIn = (0, compiler_core_1.isCoreComponent)(tag) || context.isBuiltInComponent(tag);
|
||||
if (builtIn) {
|
||||
return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
|
||||
}
|
||||
// 3. user component (from setup bindings)
|
||||
const fromSetup = resolveSetupReference(tag, context);
|
||||
if (fromSetup) {
|
||||
return (context.bindingComponents[tag] = {
|
||||
name: fromSetup,
|
||||
type: "setup" /* BindingComponentTypes.SETUP */,
|
||||
});
|
||||
}
|
||||
const dotIndex = tag.indexOf('.');
|
||||
if (dotIndex > 0) {
|
||||
return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
|
||||
}
|
||||
// 4. Self referencing component (inferred from filename)
|
||||
if (context.selfName && (0, shared_1.capitalize)((0, shared_1.camelize)(tag)) === context.selfName) {
|
||||
return (context.bindingComponents[tag] = {
|
||||
name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
|
||||
type: "self" /* BindingComponentTypes.SELF */,
|
||||
});
|
||||
}
|
||||
// 5. user component (resolve)
|
||||
context.bindingComponents[tag] = {
|
||||
name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
|
||||
type: "unknown" /* BindingComponentTypes.UNKNOWN */,
|
||||
};
|
||||
context.helper(compiler_core_1.RESOLVE_COMPONENT);
|
||||
}
|
||||
function resolveSetupReference(name, context) {
|
||||
const bindings = context.bindingMetadata;
|
||||
if (!bindings || bindings.__isScriptSetup === false) {
|
||||
return;
|
||||
}
|
||||
const camelName = (0, shared_1.camelize)(name);
|
||||
const PascalName = (0, shared_1.capitalize)(camelName);
|
||||
const checkType = (type) => {
|
||||
if (bindings[name] === type) {
|
||||
return name;
|
||||
}
|
||||
if (bindings[camelName] === type) {
|
||||
return camelName;
|
||||
}
|
||||
if (bindings[PascalName] === type) {
|
||||
return PascalName;
|
||||
}
|
||||
};
|
||||
const fromConst = checkType(compiler_core_1.BindingTypes.SETUP_CONST) ||
|
||||
checkType(compiler_core_1.BindingTypes.SETUP_REACTIVE_CONST) ||
|
||||
checkType(compiler_core_1.BindingTypes.LITERAL_CONST);
|
||||
if (fromConst) {
|
||||
return context.inline
|
||||
? // in inline mode, const setup bindings (e.g. imports) can be used as-is
|
||||
fromConst
|
||||
: `$setup[${JSON.stringify(fromConst)}]`;
|
||||
}
|
||||
const fromMaybeRef = checkType(compiler_core_1.BindingTypes.SETUP_LET) ||
|
||||
checkType(compiler_core_1.BindingTypes.SETUP_REF) ||
|
||||
checkType(compiler_core_1.BindingTypes.SETUP_MAYBE_REF);
|
||||
if (fromMaybeRef) {
|
||||
return context.inline
|
||||
? // setup scope bindings that may be refs need to be unrefed
|
||||
`${context.helperString(compiler_core_1.UNREF)}(${fromMaybeRef})`
|
||||
: `$setup[${JSON.stringify(fromMaybeRef)}]`;
|
||||
}
|
||||
}
|
||||
function processProps(node, context, props = node.props) {
|
||||
const { tag } = node;
|
||||
const isComponent = node.tagType === compiler_core_1.ElementTypes.COMPONENT;
|
||||
const isPluginComponent = isComponent && context.isMiniProgramComponent(node.tag) === 'plugin';
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i];
|
||||
if (prop.type === compiler_core_1.NodeTypes.DIRECTIVE) {
|
||||
// directives
|
||||
const { name, arg, loc } = prop;
|
||||
const isVBind = name === 'bind';
|
||||
const isVOn = name === 'on';
|
||||
// skip v-slot - it is handled by its dedicated transform.
|
||||
if (name === 'slot') {
|
||||
if (!isComponent) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_MISPLACED, loc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// skip v-once/v-memo - they are handled by dedicated transforms.
|
||||
if (name === 'once' || name === 'memo') {
|
||||
continue;
|
||||
}
|
||||
// skip v-is and :is on <component>
|
||||
if (name === 'is' ||
|
||||
(isVBind && (0, compiler_core_1.isStaticArgOf)(arg, 'is') && (0, uni_shared_1.isComponentTag)(tag))) {
|
||||
continue;
|
||||
}
|
||||
if (isVBind || isVOn) {
|
||||
// v-on=""
|
||||
// v-bind=""
|
||||
if (!arg) {
|
||||
if (isVOn) {
|
||||
context.onError((0, errors_1.createMPCompilerError)(0 /* MPErrorCodes.X_V_ON_NO_ARGUMENT */, loc));
|
||||
}
|
||||
if (isVBind && (!isComponent || isPluginComponent)) {
|
||||
context.onError((0, errors_1.createMPCompilerError)(2 /* MPErrorCodes.X_V_BIND_NO_ARGUMENT */, loc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// v-on:[a]=""
|
||||
// v-on:[a.b]=""
|
||||
// v-bind:[a]=""
|
||||
// v-bind:[a.b]=""
|
||||
if (!(arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.isStatic)) {
|
||||
if (isVOn) {
|
||||
context.onError((0, errors_1.createMPCompilerError)(1 /* MPErrorCodes.X_V_ON_DYNAMIC_EVENT */, loc));
|
||||
}
|
||||
if (isVBind && (!isComponent || isPluginComponent)) {
|
||||
context.onError((0, errors_1.createMPCompilerError)(3 /* MPErrorCodes.X_V_BIND_DYNAMIC_ARGUMENT */, loc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const directiveTransform = context.directiveTransforms[name];
|
||||
if (name !== 'model' && directiveTransform) {
|
||||
const { props } = directiveTransform(prop, node, context);
|
||||
if (props.length) {
|
||||
prop.exp = props[0].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const transformVModel = (context.directiveTransforms.model ||
|
||||
vModel_1.transformModel);
|
||||
processVModel(node, transformVModel, context);
|
||||
}
|
||||
exports.processProps = processProps;
|
||||
function processVModel(node, transformVModel, context) {
|
||||
const { props } = node;
|
||||
const dirs = [];
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i];
|
||||
if (prop.type === compiler_core_1.NodeTypes.DIRECTIVE && prop.name === 'model') {
|
||||
dirs.push(...transformVModel(prop, node, context)
|
||||
.props);
|
||||
props.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (dirs.length) {
|
||||
props.push(...dirs);
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import { type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
import type { NodeTransform, TransformContext } from '../transform';
|
||||
export declare const transformExpression: NodeTransform;
|
||||
export declare function processExpression(node: SimpleExpressionNode, context: TransformContext, asParams?: boolean, asRawStatements?: boolean, localVars?: Record<string, number>): ExpressionNode;
|
||||
export declare function isBuiltInIdentifier(id: string | ExpressionNode): boolean;
|
||||
Generated
Vendored
+299
@@ -0,0 +1,299 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isBuiltInIdentifier = exports.processExpression = exports.transformExpression = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const isLiteralWhitelisted = /*#__PURE__*/ (0, shared_1.makeMap)('true,false,null,this');
|
||||
const transformExpression = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.INTERPOLATION) {
|
||||
node.content = processExpression(node.content, context);
|
||||
}
|
||||
else if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
// handle directives on element
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const dir = node.props[i];
|
||||
// do not process for v-on & v-for since they are special handled
|
||||
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE && dir.name !== 'for') {
|
||||
const exp = dir.exp;
|
||||
const arg = dir.arg;
|
||||
// do not process exp if this is v-on:arg - we need special handling
|
||||
// for wrapping inline statements.
|
||||
if (exp &&
|
||||
exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
!(dir.name === 'on' && arg)) {
|
||||
dir.exp = processExpression(exp, context,
|
||||
// slot args must be processed as function params
|
||||
dir.name === 'slot');
|
||||
}
|
||||
if (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
|
||||
dir.arg = processExpression(arg, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.transformExpression = transformExpression;
|
||||
// Important: since this function uses Node.js only dependencies, it should
|
||||
// always be used with a leading !__BROWSER__ check so that it can be
|
||||
// tree-shaken from the browser build.
|
||||
function processExpression(node, context,
|
||||
// some expressions like v-slot props & v-for aliases should be parsed as
|
||||
// function params
|
||||
asParams = false,
|
||||
// v-on handler values may contain multiple statements
|
||||
asRawStatements = false, localVars = Object.create(context.identifiers)) {
|
||||
if (!context.prefixIdentifiers || !node.content.trim()) {
|
||||
return node;
|
||||
}
|
||||
const { inline, bindingMetadata } = context;
|
||||
const rewriteIdentifier = (raw, parent, id) => {
|
||||
const type = (0, shared_1.hasOwn)(bindingMetadata, raw) && bindingMetadata[raw];
|
||||
if (inline) {
|
||||
// x = y
|
||||
const isAssignmentLVal = parent && parent.type === 'AssignmentExpression' && parent.left === id;
|
||||
// x++
|
||||
const isUpdateArg = parent && parent.type === 'UpdateExpression' && parent.argument === id;
|
||||
// ({ x } = y)
|
||||
const isDestructureAssignment = parent && (0, compiler_core_1.isInDestructureAssignment)(parent, parentStack);
|
||||
if (isConst(type) || localVars[raw]) {
|
||||
return raw;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_REF) {
|
||||
return `${raw}.value`;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_MAYBE_REF) {
|
||||
// const binding that may or may not be ref
|
||||
// if it's not a ref, then assignments don't make sense -
|
||||
// so we ignore the non-ref assignment case and generate code
|
||||
// that assumes the value to be a ref for more efficiency
|
||||
return isAssignmentLVal || isUpdateArg || isDestructureAssignment
|
||||
? `${raw}.value`
|
||||
: `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_LET) {
|
||||
if (isAssignmentLVal) {
|
||||
// let binding.
|
||||
// this is a bit more tricky as we need to cover the case where
|
||||
// let is a local non-ref value, and we need to replicate the
|
||||
// right hand side value.
|
||||
// x = y --> isRef(x) ? x.value = y : x = y
|
||||
const { right: rVal, operator } = parent;
|
||||
const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1);
|
||||
const rExpString = stringifyExpression(processExpression((0, compiler_core_1.createSimpleExpression)(rExp, false), context, false, false, knownIds));
|
||||
return `${context.helperString(compiler_core_1.IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${raw}.value ${operator} ${rExpString} : ${raw}`;
|
||||
}
|
||||
else if (isUpdateArg) {
|
||||
// make id replace parent in the code range so the raw update operator
|
||||
// is removed
|
||||
id.start = parent.start;
|
||||
id.end = parent.end;
|
||||
const { prefix: isPrefix, operator } = parent;
|
||||
const prefix = isPrefix ? operator : ``;
|
||||
const postfix = isPrefix ? `` : operator;
|
||||
// let binding.
|
||||
// x++ --> isRef(a) ? a.value++ : a++
|
||||
return `${context.helperString(compiler_core_1.IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`;
|
||||
}
|
||||
else if (isDestructureAssignment) {
|
||||
// TODO
|
||||
// let binding in a destructure assignment - it's very tricky to
|
||||
// handle both possible cases here without altering the original
|
||||
// structure of the code, so we just assume it's not a ref here
|
||||
// for now
|
||||
return raw;
|
||||
}
|
||||
else {
|
||||
return `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
|
||||
}
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.PROPS) {
|
||||
// use __props which is generated by compileScript so in ts mode
|
||||
// it gets correct type
|
||||
return (0, shared_1.genPropsAccessExp)(raw);
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.PROPS_ALIASED) {
|
||||
// prop with a different local alias (from defineProps() destructure)
|
||||
return (0, shared_1.genPropsAccessExp)(bindingMetadata.__propsAliases[raw]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((type && type.startsWith('setup')) ||
|
||||
type === compiler_core_1.BindingTypes.LITERAL_CONST) {
|
||||
// setup bindings in non-inline mode
|
||||
return `$setup.${raw}`;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.PROPS_ALIASED) {
|
||||
return `$props['${bindingMetadata.__propsAliases[raw]}']`;
|
||||
}
|
||||
else if (type) {
|
||||
return `$${type}.${raw}`;
|
||||
}
|
||||
}
|
||||
// fallback to ctx
|
||||
return `_ctx.${raw}`;
|
||||
};
|
||||
// fast path if expression is a simple identifier.
|
||||
const rawExp = node.content;
|
||||
// bail constant on parens (function invocation) and dot (member access)
|
||||
const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0;
|
||||
if ((0, compiler_core_1.isSimpleIdentifier)(rawExp)) {
|
||||
const isScopeVarReference = context.identifiers[rawExp];
|
||||
const isAllowedGlobal = (0, shared_1.isGloballyWhitelisted)(rawExp);
|
||||
const isLiteral = isLiteralWhitelisted(rawExp);
|
||||
const isFilter = context.filters.includes(rawExp);
|
||||
const isBuiltIn = isBuiltInIdentifier(rawExp);
|
||||
if (!asParams &&
|
||||
!isScopeVarReference &&
|
||||
!isAllowedGlobal &&
|
||||
!isLiteral &&
|
||||
!isFilter &&
|
||||
!isBuiltIn) {
|
||||
// const bindings exposed from setup can be skipped for patching but
|
||||
// cannot be hoisted to module scope
|
||||
if (isConst(bindingMetadata[node.content])) {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_SKIP_PATCH;
|
||||
}
|
||||
node.content = rewriteIdentifier(rawExp);
|
||||
}
|
||||
else if (!isScopeVarReference) {
|
||||
if (isLiteral) {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_STRINGIFY;
|
||||
}
|
||||
else {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_HOIST;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
let ast;
|
||||
// exp needs to be parsed differently:
|
||||
// 1. Multiple inline statements (v-on, with presence of `;`): parse as raw
|
||||
// exp, but make sure to pad with spaces for consistent ranges
|
||||
// 2. Expressions: wrap with parens (for e.g. object expressions)
|
||||
// 3. Function arguments (v-for, v-slot): place in a function argument position
|
||||
const source = asRawStatements
|
||||
? ` ${rawExp} `
|
||||
: `(${rawExp})${asParams ? `=>{}` : ``}`;
|
||||
try {
|
||||
ast = (0, parser_1.parse)(source, {
|
||||
plugins: context.expressionPlugins,
|
||||
}).program;
|
||||
}
|
||||
catch (e) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_INVALID_EXPRESSION, node.loc, undefined, '\n' + source + '\n' + e.message));
|
||||
return node;
|
||||
}
|
||||
const ids = [];
|
||||
const parentStack = [];
|
||||
const knownIds = Object.create(context.identifiers);
|
||||
context.filters.forEach((name) => {
|
||||
knownIds[name] = 1;
|
||||
});
|
||||
(0, compiler_core_1.walkIdentifiers)(ast, (node, parent, _, isReferenced, isLocal) => {
|
||||
if ((0, compiler_core_1.isStaticPropertyKey)(node, parent)) {
|
||||
return;
|
||||
}
|
||||
const needPrefix = isReferenced && canPrefix(node);
|
||||
if (needPrefix && !isLocal) {
|
||||
if ((0, compiler_core_1.isStaticProperty)(parent) && parent.shorthand) {
|
||||
// property shorthand like { foo }, we need to add the key since
|
||||
// we rewrite the value
|
||||
;
|
||||
node.prefix = `${node.name}: `;
|
||||
}
|
||||
node.name = rewriteIdentifier(node.name, parent, node);
|
||||
ids.push(node);
|
||||
}
|
||||
else {
|
||||
// The identifier is considered constant unless it's pointing to a
|
||||
// local scope variable (a v-for alias, or a v-slot prop)
|
||||
if (!(needPrefix && isLocal) && !bailConstant) {
|
||||
;
|
||||
node.isConstant = true;
|
||||
}
|
||||
// also generate sub-expressions for other identifiers for better
|
||||
// source map support. (except for property keys which are static)
|
||||
ids.push(node);
|
||||
}
|
||||
}, true, // invoke on ALL identifiers
|
||||
parentStack, knownIds);
|
||||
// We break up the compound expression into an array of strings and sub
|
||||
// expressions (for identifiers that have been prefixed). In codegen, if
|
||||
// an ExpressionNode has the `.children` property, it will be used instead of
|
||||
// `.content`.
|
||||
const children = [];
|
||||
ids.sort((a, b) => a.start - b.start);
|
||||
ids.forEach((id, i) => {
|
||||
// range is offset by -1 due to the wrapping parens when parsed
|
||||
const start = id.start - 1;
|
||||
const end = id.end - 1;
|
||||
const last = ids[i - 1];
|
||||
const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);
|
||||
if (leadingText.length || id.prefix) {
|
||||
children.push(leadingText + (id.prefix || ``));
|
||||
}
|
||||
const source = rawExp.slice(start, end);
|
||||
children.push((0, compiler_core_1.createSimpleExpression)(id.name, false, {
|
||||
source,
|
||||
start: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, start),
|
||||
end: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, end),
|
||||
}, id.isConstant ? compiler_core_1.ConstantTypes.CAN_STRINGIFY : compiler_core_1.ConstantTypes.NOT_CONSTANT));
|
||||
if (i === ids.length - 1 && end < rawExp.length) {
|
||||
children.push(rawExp.slice(end));
|
||||
}
|
||||
});
|
||||
let ret;
|
||||
if (children.length) {
|
||||
ret = (0, compiler_core_1.createCompoundExpression)(children, node.loc);
|
||||
}
|
||||
else {
|
||||
ret = node;
|
||||
ret.constType = bailConstant
|
||||
? compiler_core_1.ConstantTypes.NOT_CONSTANT
|
||||
: compiler_core_1.ConstantTypes.CAN_STRINGIFY;
|
||||
}
|
||||
ret.identifiers = Object.keys(knownIds);
|
||||
return ret;
|
||||
}
|
||||
exports.processExpression = processExpression;
|
||||
function canPrefix(id) {
|
||||
// skip whitelisted globals
|
||||
if ((0, shared_1.isGloballyWhitelisted)(id.name)) {
|
||||
return false;
|
||||
}
|
||||
// special case for webpack compilation
|
||||
if (id.name === 'require') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function stringifyExpression(exp) {
|
||||
if ((0, shared_1.isString)(exp)) {
|
||||
return exp;
|
||||
}
|
||||
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
return exp.content;
|
||||
}
|
||||
else {
|
||||
return exp.children
|
||||
.map(stringifyExpression)
|
||||
.join('');
|
||||
}
|
||||
}
|
||||
const builtInIdentifiers = ['__l'];
|
||||
function isBuiltInIdentifier(id) {
|
||||
if (!(0, shared_1.isString)(id)) {
|
||||
if (id.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
return false;
|
||||
}
|
||||
id = id.content;
|
||||
}
|
||||
return builtInIdentifiers.includes(id);
|
||||
}
|
||||
exports.isBuiltInIdentifier = isBuiltInIdentifier;
|
||||
function isConst(type) {
|
||||
return (type === compiler_core_1.BindingTypes.SETUP_CONST ||
|
||||
type === compiler_core_1.BindingTypes.LITERAL_CONST ||
|
||||
type === compiler_core_1.BindingTypes.SETUP_REACTIVE_CONST);
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function isHiddenBinding({ arg, exp }: DirectiveNode): boolean | undefined;
|
||||
export declare function findStaticHiddenIndex(props: (AttributeNode | DirectiveNode)[]): number;
|
||||
export declare function findVShowIndex(props: (AttributeNode | DirectiveNode)[]): number;
|
||||
export declare function rewriteHidden(index: number, hiddenBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext): void;
|
||||
export declare function createVirtualHostHidden(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;
|
||||
Generated
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVirtualHostHidden = exports.rewriteHidden = exports.findVShowIndex = exports.findStaticHiddenIndex = exports.isHiddenBinding = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const utils_1 = require("./utils");
|
||||
function isHiddenBinding({ arg, exp }) {
|
||||
return (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'hidden');
|
||||
}
|
||||
exports.isHiddenBinding = isHiddenBinding;
|
||||
function findStaticHiddenIndex(props) {
|
||||
return props.findIndex((prop) => prop.name === 'hidden');
|
||||
}
|
||||
exports.findStaticHiddenIndex = findStaticHiddenIndex;
|
||||
function findVShowIndex(props) {
|
||||
return props.findIndex((prop) => prop.name === 'show' && prop.type === compiler_core_1.NodeTypes.DIRECTIVE);
|
||||
}
|
||||
exports.findVShowIndex = findVShowIndex;
|
||||
function rewriteHidden(index, hiddenBindingProp, props, virtualHost, context) {
|
||||
let bindingProp = hiddenBindingProp;
|
||||
const vShowIndex = findVShowIndex(props);
|
||||
if (vShowIndex > -1) {
|
||||
bindingProp = props[vShowIndex];
|
||||
}
|
||||
let expr = bindingProp.exp ? (0, ast_1.parseExpr)(bindingProp.exp, context) : undefined;
|
||||
let hiddenBindingExpr;
|
||||
if (virtualHost) {
|
||||
const staticClassPropIndex = findStaticHiddenIndex(props);
|
||||
// skyline模式hidden传undefined会导致元素被隐藏
|
||||
const virtualHostHiddenPolyfill = (0, types_1.logicalExpression)('||', (0, types_1.identifier)(uni_shared_1.VIRTUAL_HOST_HIDDEN), (0, types_1.booleanLiteral)(false));
|
||||
if (expr || staticClassPropIndex > -1) {
|
||||
let res = (0, types_1.booleanLiteral)(true);
|
||||
if (expr) {
|
||||
// TODO ignore all simple expression
|
||||
res = (0, types_1.isIdentifier)(expr)
|
||||
? expr
|
||||
: (0, types_1.identifier)((0, utils_1.rewriteExpression)(bindingProp.exp, context).content);
|
||||
if (vShowIndex > -1) {
|
||||
props.splice(vShowIndex, 1);
|
||||
res = (0, types_1.unaryExpression)('!', res);
|
||||
}
|
||||
}
|
||||
hiddenBindingExpr = (0, types_1.conditionalExpression)((0, types_1.binaryExpression)('!==', (0, types_1.identifier)(uni_shared_1.VIRTUAL_HOST_HIDDEN), (0, types_1.stringLiteral)('')), virtualHostHiddenPolyfill, res);
|
||||
}
|
||||
else {
|
||||
hiddenBindingExpr = virtualHostHiddenPolyfill;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ignore rewrite without virtualHost
|
||||
return;
|
||||
}
|
||||
hiddenBindingProp.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(hiddenBindingExpr));
|
||||
}
|
||||
exports.rewriteHidden = rewriteHidden;
|
||||
function createVirtualHostHidden(props, context) {
|
||||
const hiddenBindingProp = (0, uni_cli_shared_1.createBindDirectiveNode)('hidden', '');
|
||||
delete hiddenBindingProp.exp;
|
||||
rewriteHidden(0, hiddenBindingProp, props, true, context);
|
||||
return hiddenBindingProp;
|
||||
}
|
||||
exports.createVirtualHostHidden = createVirtualHostHidden;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function isIdBinding({ arg, exp }: DirectiveNode): boolean | undefined;
|
||||
export declare function findStaticIdIndex(props: (AttributeNode | DirectiveNode)[]): number;
|
||||
export declare function rewriteId(index: number, idBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext, isX?: boolean): void;
|
||||
export declare function createVirtualHostId(props: (AttributeNode | DirectiveNode)[], context: TransformContext, isX?: boolean): DirectiveNode;
|
||||
Generated
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVirtualHostId = exports.rewriteId = exports.findStaticIdIndex = exports.isIdBinding = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const utils_1 = require("./utils");
|
||||
function isIdBinding({ arg, exp }) {
|
||||
return arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'id';
|
||||
}
|
||||
exports.isIdBinding = isIdBinding;
|
||||
function findStaticIdIndex(props) {
|
||||
return props.findIndex((prop) => prop.name === 'id');
|
||||
}
|
||||
exports.findStaticIdIndex = findStaticIdIndex;
|
||||
function rewriteId(index, idBindingProp, props, virtualHost, context, isX = false) {
|
||||
let expr = idBindingProp.exp
|
||||
? (0, ast_1.parseExpr)(idBindingProp.exp, context)
|
||||
: undefined;
|
||||
let idBindingExpr;
|
||||
const staticIdPropIndex = findStaticIdIndex(props);
|
||||
if (staticIdPropIndex > -1) {
|
||||
idBindingExpr = (0, types_1.stringLiteral)(props[staticIdPropIndex].value.content);
|
||||
}
|
||||
else if (expr) {
|
||||
idBindingExpr =
|
||||
isX || virtualHost
|
||||
? expr
|
||||
: (0, types_1.identifier)((0, utils_1.rewriteExpression)(idBindingProp.exp, context).content);
|
||||
}
|
||||
else {
|
||||
idBindingExpr = (0, types_1.stringLiteral)('');
|
||||
}
|
||||
if (virtualHost) {
|
||||
idBindingExpr = (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.GEN_UNI_ELEMENT_ID)), [(0, types_1.identifier)('_ctx'), idBindingExpr]);
|
||||
if (!isX) {
|
||||
// 非uni-app-x id绑定表达式直接生成在了模板内
|
||||
idBindingExpr = (0, types_1.identifier)((0, utils_1.rewriteExpression)((0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(idBindingExpr)), context).content);
|
||||
}
|
||||
}
|
||||
idBindingProp.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(idBindingExpr));
|
||||
}
|
||||
exports.rewriteId = rewriteId;
|
||||
function createVirtualHostId(props, context, isX = false) {
|
||||
const idBindingProp = (0, uni_cli_shared_1.createBindDirectiveNode)('id', '');
|
||||
delete idBindingProp.exp;
|
||||
rewriteId(0, idBindingProp, props, true, context, isX);
|
||||
return idBindingProp;
|
||||
}
|
||||
exports.createVirtualHostId = createVirtualHostId;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformIdentifier: NodeTransform;
|
||||
Generated
Vendored
+215
@@ -0,0 +1,215 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformIdentifier = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const utils_1 = require("./utils");
|
||||
const transformClass_1 = require("./transformClass");
|
||||
const transformStyle_1 = require("./transformStyle");
|
||||
const transformHidden_1 = require("./transformHidden");
|
||||
const transformId_1 = require("./transformId");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const transformSlot_1 = require("./transformSlot");
|
||||
const vSlot_1 = require("./vSlot");
|
||||
const transformRef_1 = require("./transformRef");
|
||||
const transformComponent_1 = require("./transformComponent");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const transformUniElement_1 = require("./transformUniElement");
|
||||
const transformIdentifier = (node, context) => {
|
||||
return function transformIdentifier() {
|
||||
if (node.type === compiler_core_1.NodeTypes.INTERPOLATION) {
|
||||
const content = node.content;
|
||||
let isFilter = false;
|
||||
if (content.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
const firstChild = content.children[0];
|
||||
isFilter =
|
||||
!(0, shared_1.isString)(firstChild) &&
|
||||
!(0, shared_1.isSymbol)(firstChild) &&
|
||||
firstChild.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
context.filters.includes(firstChild.content);
|
||||
}
|
||||
if (!isFilter) {
|
||||
node.content = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
`${context.helperString(runtimeHelpers_1.TO_DISPLAY_STRING)}(`,
|
||||
content,
|
||||
`)`,
|
||||
]), context);
|
||||
}
|
||||
}
|
||||
else if ((0, compiler_core_1.isSlotOutlet)(node)) {
|
||||
(0, transformSlot_1.rewriteSlot)(node, context);
|
||||
}
|
||||
else if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
let hasClassBinding = false;
|
||||
let hasStyleBinding = false;
|
||||
let hasHiddenBinding = false;
|
||||
let hasIdBinding = false;
|
||||
const { props } = node;
|
||||
const virtualHost = !!(context.miniProgram.component?.mergeVirtualHostAttributes &&
|
||||
context.rootNode === node);
|
||||
(0, transformRef_1.rewriteRef)(node, context);
|
||||
if (context.isX) {
|
||||
if (virtualHost) {
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const dir = props[i];
|
||||
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE) {
|
||||
if ((0, transformId_1.isIdBinding)(dir)) {
|
||||
hasIdBinding = true;
|
||||
(0, transformId_1.rewriteId)(i, dir, props, virtualHost, context, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasIdBinding) {
|
||||
hasIdBinding = true;
|
||||
props.push((0, transformId_1.createVirtualHostId)(props, context, true));
|
||||
}
|
||||
const staticIdIndex = (0, transformId_1.findStaticIdIndex)(props);
|
||||
if (staticIdIndex > -1) {
|
||||
props.splice(staticIdIndex, 1);
|
||||
}
|
||||
}
|
||||
(0, transformUniElement_1.rewriteId)(node, context);
|
||||
}
|
||||
if ((0, uni_cli_shared_1.isUserComponent)(node, context)) {
|
||||
(0, transformComponent_1.rewriteBinding)(node, context);
|
||||
}
|
||||
let elementId = '';
|
||||
let skipIndex = [];
|
||||
// 第一步:在 x 中,先处理 id 属性,用于提前获取 elementId 对应的变量名
|
||||
if (context.isX) {
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const dir = props[i];
|
||||
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE) {
|
||||
const { arg, exp } = dir;
|
||||
if (arg && exp && (0, uni_cli_shared_1.isSimpleExpressionNode)(arg)) {
|
||||
if (arg.content === 'id' || arg.content === utils_1.ATTR_ELEMENT_ID) {
|
||||
dir.exp = (0, utils_1.rewriteExpression)(exp, context);
|
||||
elementId = dir.exp.content;
|
||||
skipIndex.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
if (context.isX) {
|
||||
// 已经处理过了
|
||||
if (skipIndex.includes(i)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const dir = props[i];
|
||||
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE) {
|
||||
const arg = dir.arg;
|
||||
if (arg) {
|
||||
// TODO 指令暂不不支持动态参数,v-bind:[arg] v-on:[event]
|
||||
if (!(arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.isStatic)) {
|
||||
// v-slot:[slotName] 支持
|
||||
if (dir.name === 'slot') {
|
||||
(0, vSlot_1.rewriteVSlot)(dir, context);
|
||||
}
|
||||
else {
|
||||
props.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
const exp = dir.exp;
|
||||
if (exp) {
|
||||
if (isBuiltIn(dir)) {
|
||||
// noop
|
||||
}
|
||||
else if ((0, transformClass_1.isClassBinding)(dir)) {
|
||||
hasClassBinding = true;
|
||||
(0, transformClass_1.rewriteClass)(i, dir, props, virtualHost, context);
|
||||
}
|
||||
else if ((0, transformStyle_1.isStyleBinding)(dir)) {
|
||||
hasStyleBinding = true;
|
||||
(0, transformStyle_1.rewriteStyle)(i, dir, props, virtualHost, context, elementId);
|
||||
}
|
||||
else if ((0, transformHidden_1.isHiddenBinding)(dir)) {
|
||||
hasHiddenBinding = true;
|
||||
(0, transformHidden_1.rewriteHidden)(i, dir, props, virtualHost, context);
|
||||
}
|
||||
else if ((0, transformId_1.isIdBinding)(dir)) {
|
||||
hasIdBinding = true;
|
||||
(0, transformId_1.rewriteId)(i, dir, props, virtualHost, context);
|
||||
}
|
||||
else if ((0, transformComponent_1.isPropsBinding)(dir)) {
|
||||
(0, transformComponent_1.rewritePropsBinding)(dir, node, context);
|
||||
}
|
||||
else {
|
||||
if (context.isX &&
|
||||
elementId &&
|
||||
arg &&
|
||||
(0, uni_cli_shared_1.isSimpleExpressionNode)(arg)) {
|
||||
if (arg.content === utils_1.ATTR_SET_ELEMENT_STYLE) {
|
||||
dir.exp = (0, compiler_core_1.createSimpleExpression)(`$eS[${elementId}]`);
|
||||
}
|
||||
else if (arg.content === utils_1.ATTR_SET_ELEMENT_ANIMATION) {
|
||||
dir.exp = (0, compiler_core_1.createSimpleExpression)(`$eA[${elementId}]`);
|
||||
}
|
||||
else {
|
||||
dir.exp = (0, utils_1.rewriteExpression)(exp, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dir.exp = (0, utils_1.rewriteExpression)(exp, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (virtualHost) {
|
||||
if (!hasClassBinding) {
|
||||
hasClassBinding = true;
|
||||
props.push((0, transformClass_1.createVirtualHostClass)(props, context));
|
||||
}
|
||||
if (!hasStyleBinding) {
|
||||
hasStyleBinding = true;
|
||||
props.push((0, transformStyle_1.createVirtualHostStyle)(props, context));
|
||||
}
|
||||
if (!hasHiddenBinding) {
|
||||
hasHiddenBinding = true;
|
||||
props.push((0, transformHidden_1.createVirtualHostHidden)(props, context));
|
||||
}
|
||||
if (!hasIdBinding) {
|
||||
hasIdBinding = true;
|
||||
props.push((0, transformId_1.createVirtualHostId)(props, context));
|
||||
}
|
||||
}
|
||||
if (hasClassBinding) {
|
||||
const staticClassIndex = (0, transformClass_1.findStaticClassIndex)(props);
|
||||
if (staticClassIndex > -1) {
|
||||
props.splice(staticClassIndex, 1);
|
||||
}
|
||||
}
|
||||
if (hasStyleBinding) {
|
||||
const staticStyleIndex = (0, transformStyle_1.findStaticStyleIndex)(props);
|
||||
if (staticStyleIndex > -1) {
|
||||
props.splice(staticStyleIndex, 1);
|
||||
}
|
||||
}
|
||||
if (hasHiddenBinding) {
|
||||
const staticHiddenIndex = (0, transformHidden_1.findStaticHiddenIndex)(props);
|
||||
if (staticHiddenIndex > -1) {
|
||||
props.splice(staticHiddenIndex, 1);
|
||||
}
|
||||
}
|
||||
if (hasIdBinding) {
|
||||
const staticIdIndex = (0, transformId_1.findStaticIdIndex)(props);
|
||||
if (staticIdIndex > -1) {
|
||||
props.splice(staticIdIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
exports.transformIdentifier = transformIdentifier;
|
||||
const builtInProps = [utils_1.ATTR_VUE_SLOTS];
|
||||
function isBuiltIn({ arg, exp }) {
|
||||
return (arg?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
builtInProps.includes(arg.content) &&
|
||||
exp?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION);
|
||||
}
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import { type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { ForElementNode } from './vFor';
|
||||
export declare function isSelfKey({ arg, exp }: DirectiveNode, vFor: ForElementNode['vFor'] | false): boolean | undefined;
|
||||
export declare function rewriteSelfKey(dir: DirectiveNode): void;
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.rewriteSelfKey = exports.isSelfKey = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
function isSelfKey({ arg, exp }, vFor) {
|
||||
return (vFor &&
|
||||
arg &&
|
||||
exp &&
|
||||
arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
arg.content === 'key' &&
|
||||
exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
exp.content === vFor.valueAlias);
|
||||
}
|
||||
exports.isSelfKey = isSelfKey;
|
||||
function rewriteSelfKey(dir) {
|
||||
;
|
||||
dir.exp.content = '*this';
|
||||
}
|
||||
exports.rewriteSelfKey = rewriteSelfKey;
|
||||
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import { type AttributeNode, type DirectiveNode, type ElementNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function rewriteRef(node: ElementNode, context: TransformContext): void;
|
||||
export declare function parseRefCode(prop: AttributeNode | DirectiveNode, context: TransformContext): {
|
||||
code: string;
|
||||
refKey: string;
|
||||
};
|
||||
export declare function rewriteRefProp(helper: symbol, prop: AttributeNode | DirectiveNode, idProp: AttributeNode | DirectiveNode, opts: Record<string, any>, context: TransformContext): void;
|
||||
Generated
Vendored
+126
@@ -0,0 +1,126 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.rewriteRefProp = exports.parseRefCode = exports.rewriteRef = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const codegen_1 = require("../codegen");
|
||||
const ast_1 = require("../ast");
|
||||
function rewriteRef(node, context) {
|
||||
const vueIdProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_ID);
|
||||
if (!vueIdProp) {
|
||||
return;
|
||||
}
|
||||
const refProp = (0, compiler_core_1.findProp)(node, 'u-' + uni_cli_shared_1.VUE_REF) || (0, compiler_core_1.findProp)(node, 'u-' + uni_cli_shared_1.VUE_REF_IN_FOR);
|
||||
if (!refProp) {
|
||||
return;
|
||||
}
|
||||
if ((0, compiler_core_1.findProp)(node, 'ref')) {
|
||||
// 支付宝小程序
|
||||
const code = parseAlipayRefCode(refProp, context);
|
||||
if (code && context.inline && !(0, uni_cli_shared_1.isDirectiveNode)(refProp)) {
|
||||
refProp.value.content = code;
|
||||
const refPropIndex = node.props.findIndex((prop) => prop === refProp);
|
||||
node.props.splice(refPropIndex, 1, (0, uni_cli_shared_1.createBindDirectiveNode)(refProp.name, code));
|
||||
}
|
||||
}
|
||||
else {
|
||||
rewriteRefProp(runtimeHelpers_1.SET_REF, refProp, vueIdProp, {}, context);
|
||||
}
|
||||
}
|
||||
exports.rewriteRef = rewriteRef;
|
||||
function parseRef(prop, context) {
|
||||
let expr;
|
||||
let refKey = '';
|
||||
const isDir = (0, uni_cli_shared_1.isDirectiveNode)(prop);
|
||||
if (isDir) {
|
||||
if (prop.exp) {
|
||||
expr = (0, ast_1.parseExpr)(prop.exp, context, prop.exp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const { value } = prop;
|
||||
if (value && value.content) {
|
||||
if (context.inline && context.bindingMetadata[value.content]) {
|
||||
expr = (0, types_1.identifier)(value.content);
|
||||
refKey = value.content;
|
||||
}
|
||||
else {
|
||||
expr = (0, types_1.stringLiteral)(value.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { expr, refKey };
|
||||
}
|
||||
function parseRefCode(prop, context) {
|
||||
const { expr, refKey } = parseRef(prop, context);
|
||||
if (!expr) {
|
||||
return { code: '', refKey };
|
||||
}
|
||||
return { code: (0, codegen_1.genBabelExpr)(expr), refKey };
|
||||
}
|
||||
exports.parseRefCode = parseRefCode;
|
||||
function rewriteRefProp(helper, prop, idProp, opts, context) {
|
||||
let id = '';
|
||||
if ((0, uni_cli_shared_1.isDirectiveNode)(idProp)) {
|
||||
const vueIdExpr = (0, ast_1.parseExpr)(idProp.exp, context, idProp.exp);
|
||||
if (vueIdExpr) {
|
||||
id = (0, codegen_1.genBabelExpr)(vueIdExpr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
id = `'${idProp.value.content}'`;
|
||||
}
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
const { code, refKey } = parseRefCode(prop, context);
|
||||
if (refKey) {
|
||||
opts.k = refKey;
|
||||
}
|
||||
if (context.inVFor) {
|
||||
opts.f = 1;
|
||||
}
|
||||
(0, utils_1.parseExprWithRewrite)(context.helperString(helper) +
|
||||
'(' +
|
||||
code +
|
||||
', ' +
|
||||
id +
|
||||
(Object.keys(opts).length ? ', ' + JSON.stringify(opts) : '') +
|
||||
')', prop.loc, context);
|
||||
}
|
||||
exports.rewriteRefProp = rewriteRefProp;
|
||||
function parseAlipayRefCode(prop, context) {
|
||||
let expr;
|
||||
const isDir = (0, uni_cli_shared_1.isDirectiveNode)(prop);
|
||||
if (isDir) {
|
||||
if (prop.exp) {
|
||||
expr = (0, ast_1.parseExpr)(prop.exp, context, prop.exp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (prop.value?.content) {
|
||||
expr = context.inline
|
||||
? processInlineRef(prop, context)
|
||||
: (0, types_1.stringLiteral)(prop.value.content);
|
||||
}
|
||||
}
|
||||
if (!expr) {
|
||||
return;
|
||||
}
|
||||
return (0, codegen_1.genBabelExpr)(expr);
|
||||
}
|
||||
function processInlineRef(prop, context) {
|
||||
const properties = [];
|
||||
const { refKey } = parseRef(prop, context);
|
||||
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('r'), (0, types_1.identifier)(prop.value.content)));
|
||||
if (refKey) {
|
||||
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('k'), (0, types_1.stringLiteral)(refKey)));
|
||||
}
|
||||
if (context.inVFor) {
|
||||
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('f'), (0, types_1.numericLiteral)(1)));
|
||||
}
|
||||
return (0, types_1.arrowFunctionExpression)([], (0, types_1.objectExpression)(properties));
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformRoot: NodeTransform;
|
||||
Generated
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformRoot = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const ast_1 = require("../ast");
|
||||
const types_1 = require("@babel/types");
|
||||
const codegen_1 = require("../codegen");
|
||||
const transformRoot = (node, context) => {
|
||||
if (node.type !== compiler_core_1.NodeTypes.ROOT) {
|
||||
return;
|
||||
}
|
||||
if (context.bindingCssVars.length) {
|
||||
node.children.forEach((child) => {
|
||||
if (child.type !== compiler_core_1.NodeTypes.ELEMENT) {
|
||||
return;
|
||||
}
|
||||
addCssVars(child, context);
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.transformRoot = transformRoot;
|
||||
const CSS_VARS = '__cssVars()';
|
||||
function addCssVars(node, context) {
|
||||
const styleProp = (0, compiler_core_1.findProp)(node, 'style', true);
|
||||
if (!styleProp) {
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('style', CSS_VARS));
|
||||
}
|
||||
else {
|
||||
if (styleProp.exp?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
let expr = (0, ast_1.parseExpr)(styleProp.exp.content, context);
|
||||
if ((0, types_1.isArrayExpression)(expr)) {
|
||||
expr.elements.push((0, types_1.identifier)(CSS_VARS));
|
||||
}
|
||||
else {
|
||||
expr = (0, types_1.arrayExpression)([expr, (0, types_1.identifier)(CSS_VARS)]);
|
||||
}
|
||||
styleProp.exp.content = (0, codegen_1.genBabelExpr)(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { type DirectiveNode, type SlotOutletNode } from '@vue/compiler-core';
|
||||
import { type TransformContext } from '../transform';
|
||||
export declare function rewriteSlot(node: SlotOutletNode, context: TransformContext): void;
|
||||
export interface NameScopedSlotDirectiveNode extends DirectiveNode {
|
||||
slotName: string;
|
||||
}
|
||||
export declare function parseVForKeyAlias(context: TransformContext): string[];
|
||||
Generated
Vendored
+188
@@ -0,0 +1,188 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseVForKeyAlias = exports.rewriteSlot = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const codegen_1 = require("../codegen");
|
||||
const transform_1 = require("../transform");
|
||||
const transformElement_1 = require("./transformElement");
|
||||
const utils_1 = require("./utils");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const __1 = require("..");
|
||||
const ast_1 = require("../ast");
|
||||
function rewriteSlot(node, context) {
|
||||
let slotName = `"${uni_shared_1.SLOT_DEFAULT_NAME}"`;
|
||||
let hasOtherDir = false;
|
||||
const nonNameProps = [];
|
||||
const { props } = node;
|
||||
// 默认插槽强制设置name
|
||||
if (!(0, compiler_core_1.findProp)(node, 'name')) {
|
||||
props.unshift((0, uni_cli_shared_1.createAttributeNode)('name', 'default'));
|
||||
}
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const p = props[i];
|
||||
if (p.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
if (p.value) {
|
||||
if (p.name === 'name') {
|
||||
p.value.content = (0, uni_shared_1.dynamicSlotName)(p.value.content);
|
||||
slotName = JSON.stringify(p.value.content);
|
||||
}
|
||||
else {
|
||||
p.name = (0, shared_1.camelize)(p.name);
|
||||
nonNameProps.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (p.name !== 'bind') {
|
||||
hasOtherDir = true;
|
||||
}
|
||||
if (p.name === 'bind' && (0, compiler_core_1.isStaticArgOf)(p.arg, 'name')) {
|
||||
if (p.exp) {
|
||||
slotName = (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(__1.DYNAMIC_SLOT) + '(',
|
||||
p.exp,
|
||||
')',
|
||||
]);
|
||||
let slotKey;
|
||||
const keys = parseVForKeyAlias(context);
|
||||
if (keys.length) {
|
||||
const babelNode = (0, ast_1.parseExpr)(p.exp, context);
|
||||
// 在 v-for 中,判断是否插槽名使用 v-for 的 key 变量
|
||||
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, keys)) {
|
||||
slotKey = parseScopedSlotKey(context);
|
||||
}
|
||||
}
|
||||
p.exp = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(__1.DYNAMIC_SLOT) + '(',
|
||||
p.exp,
|
||||
slotKey ? `+'-'+` + slotKey : '',
|
||||
')',
|
||||
]), context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (p.name === 'bind' && p.arg && (0, compiler_core_1.isStaticExp)(p.arg)) {
|
||||
p.arg.content = (0, shared_1.camelize)(p.arg.content);
|
||||
}
|
||||
nonNameProps.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasOtherDir) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET, node.loc));
|
||||
}
|
||||
if (nonNameProps.length > 0) {
|
||||
(0, transformElement_1.processProps)(node, context, nonNameProps);
|
||||
const properties = [];
|
||||
nonNameProps.forEach((prop) => {
|
||||
const property = transformProperty(prop, context);
|
||||
property && properties.push(property);
|
||||
});
|
||||
if (properties.length) {
|
||||
transformScopedSlotName(node, context);
|
||||
const vForIndexAlias = parseVForIndexAlias(context);
|
||||
(0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.RENDER_SLOT) + '(',
|
||||
slotName,
|
||||
',',
|
||||
`{${properties.join(',')}}`,
|
||||
`${vForIndexAlias ? ',' + parseScopedSlotKey(context) : ''}`,
|
||||
')',
|
||||
]), context);
|
||||
}
|
||||
else {
|
||||
// 非作用域默认插槽直接移除命名
|
||||
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
|
||||
(0, utils_1.removeAttribute)(node, 'name');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 非作用域默认插槽直接移除命名
|
||||
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
|
||||
(0, utils_1.removeAttribute)(node, 'name');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.rewriteSlot = rewriteSlot;
|
||||
function parseVForIndexAlias(context) {
|
||||
let { currentScope } = context;
|
||||
while (currentScope) {
|
||||
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
|
||||
return currentScope.indexAlias;
|
||||
}
|
||||
currentScope = currentScope.parent;
|
||||
}
|
||||
}
|
||||
function transformScopedSlotName(node, context) {
|
||||
if (!context.miniProgram.slot.dynamicSlotNames) {
|
||||
return;
|
||||
}
|
||||
const slotKey = parseScopedSlotKey(context);
|
||||
if (!slotKey) {
|
||||
return;
|
||||
}
|
||||
const nameProps = (0, compiler_core_1.findProp)(node, 'name');
|
||||
if (nameProps && nameProps.type === compiler_core_1.NodeTypes.ATTRIBUTE && nameProps.value) {
|
||||
const { props } = node;
|
||||
props.splice(props.indexOf(nameProps), 1, createScopedSlotDirectiveNode(nameProps.value.content, slotKey, context));
|
||||
}
|
||||
}
|
||||
function createScopedSlotDirectiveNode(name, slotKey, context) {
|
||||
const dir = (0, uni_cli_shared_1.createBindDirectiveNode)('name', (0, utils_1.rewriteExpression)((0, compiler_core_1.createSimpleExpression)(`"${name}-"+` + slotKey), context)
|
||||
.content);
|
||||
// 存储原始的 slot 名称
|
||||
dir.slotName = name;
|
||||
return dir;
|
||||
}
|
||||
function parseVForKeyAlias(context) {
|
||||
let { currentScope } = context;
|
||||
const keys = [];
|
||||
while (currentScope) {
|
||||
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
|
||||
keys.push(currentScope.keyAlias);
|
||||
}
|
||||
currentScope = currentScope.parent;
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
exports.parseVForKeyAlias = parseVForKeyAlias;
|
||||
function parseVForIndexes(context) {
|
||||
let { currentScope } = context;
|
||||
const indexes = [];
|
||||
while (currentScope) {
|
||||
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
|
||||
indexes.push(currentScope.indexAlias);
|
||||
}
|
||||
currentScope = currentScope.parent;
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
function parseSlotKeyByVForIndexes(indexes) {
|
||||
return indexes.reverse().join(`+'-'+`);
|
||||
}
|
||||
function parseScopedSlotKey(context) {
|
||||
const indexes = parseVForIndexes(context);
|
||||
const inFor = !!indexes.length;
|
||||
if (inFor) {
|
||||
return parseSlotKeyByVForIndexes(indexes);
|
||||
}
|
||||
}
|
||||
function transformProperty(dir, _) {
|
||||
if ((0, uni_cli_shared_1.isDirectiveNode)(dir)) {
|
||||
if (!dir.arg || !dir.exp) {
|
||||
return;
|
||||
}
|
||||
const isStaticArg = dir.arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && dir.arg.isStatic;
|
||||
if (isStaticArg) {
|
||||
return `${dir.arg.content}:${(0, codegen_1.genExpr)(dir.exp)}`;
|
||||
}
|
||||
return `[${(0, codegen_1.genExpr)(dir.arg)}||'']:${(0, codegen_1.genExpr)(dir.exp)}`;
|
||||
}
|
||||
if (dir.value) {
|
||||
return `${dir.name}:${(0, codegen_1.genExpr)(dir.value)}`;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function isStyleBinding({ arg, exp }: DirectiveNode): boolean | undefined;
|
||||
export declare function findStaticStyleIndex(props: (AttributeNode | DirectiveNode)[]): number;
|
||||
export declare function rewriteStyle(index: number, styleBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext, elementId?: string): void;
|
||||
export declare function createVirtualHostStyle(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;
|
||||
Generated
Vendored
+190
@@ -0,0 +1,190 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVirtualHostStyle = exports.rewriteStyle = exports.findStaticStyleIndex = exports.isStyleBinding = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const utils_1 = require("./utils");
|
||||
function isStyleBinding({ arg, exp }) {
|
||||
return (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'style');
|
||||
}
|
||||
exports.isStyleBinding = isStyleBinding;
|
||||
function findStaticStyleIndex(props) {
|
||||
return props.findIndex((prop) => prop.name === 'style');
|
||||
}
|
||||
exports.findStaticStyleIndex = findStaticStyleIndex;
|
||||
function rewriteStyle(index, styleBindingProp, props, virtualHost, context, elementId) {
|
||||
const expr = styleBindingProp.exp
|
||||
? (0, ast_1.parseExpr)(styleBindingProp.exp, context)
|
||||
: undefined;
|
||||
let styleBidingExpr = expr;
|
||||
if (expr) {
|
||||
if ((0, types_1.isObjectExpression)(expr)) {
|
||||
styleBidingExpr = createStyleBindingByObjectExpression(rewriteStyleObjectExpression(expr, styleBindingProp.loc, context));
|
||||
}
|
||||
else if ((0, types_1.isArrayExpression)(expr)) {
|
||||
styleBidingExpr = createStyleBindingByArrayExpression(rewriteStyleArrayExpression(expr, context));
|
||||
}
|
||||
else {
|
||||
// 在 x 中,如果有 id 且不支持 setStyle
|
||||
if (elementId &&
|
||||
context.isX &&
|
||||
!context.miniProgram.filter?.setStyle &&
|
||||
(0, uni_cli_shared_1.isCompoundExpressionNode)(styleBindingProp.exp)) {
|
||||
rewriteStyleExpression(styleBindingProp.exp, context);
|
||||
styleBidingExpr = (0, ast_1.parseExpr)(`$eS[${elementId}]`, context);
|
||||
}
|
||||
else {
|
||||
styleBidingExpr = (0, ast_1.parseExpr)(rewriteStyleExpression(styleBindingProp.exp, context).content, context);
|
||||
}
|
||||
}
|
||||
if (!styleBidingExpr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!virtualHost) {
|
||||
return;
|
||||
}
|
||||
const staticStylePropIndex = findStaticStyleIndex(props);
|
||||
if (staticStylePropIndex > -1) {
|
||||
const staticStyle = props[staticStylePropIndex].value
|
||||
.content;
|
||||
if (staticStyle.trim()) {
|
||||
if (styleBidingExpr) {
|
||||
if (index > staticStylePropIndex) {
|
||||
styleBidingExpr = (0, types_1.binaryExpression)('+', addSemicolon((0, types_1.stringLiteral)(staticStyle)), styleBidingExpr);
|
||||
}
|
||||
else {
|
||||
styleBidingExpr = (0, types_1.binaryExpression)('+', addSemicolon(styleBidingExpr), (0, types_1.stringLiteral)(staticStyle));
|
||||
}
|
||||
}
|
||||
else {
|
||||
styleBidingExpr = (0, types_1.stringLiteral)(staticStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (virtualHost) {
|
||||
styleBidingExpr = styleBidingExpr
|
||||
? (0, types_1.binaryExpression)('+', addSemicolon(styleBidingExpr), (0, types_1.identifier)(uni_shared_1.VIRTUAL_HOST_STYLE))
|
||||
: (0, types_1.identifier)(uni_shared_1.VIRTUAL_HOST_STYLE);
|
||||
}
|
||||
styleBindingProp.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(styleBidingExpr));
|
||||
}
|
||||
exports.rewriteStyle = rewriteStyle;
|
||||
function createVirtualHostStyle(props, context) {
|
||||
const styleBindingProp = (0, uni_cli_shared_1.createBindDirectiveNode)('style', '');
|
||||
delete styleBindingProp.exp;
|
||||
rewriteStyle(0, styleBindingProp, props, true, context);
|
||||
return styleBindingProp;
|
||||
}
|
||||
exports.createVirtualHostStyle = createVirtualHostStyle;
|
||||
function rewriteStyleExpression(expr, context) {
|
||||
return (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.STRINGIFY_STYLE) + '(',
|
||||
expr,
|
||||
')',
|
||||
]), context);
|
||||
}
|
||||
function rewriteStyleArrayExpression(expr, context) {
|
||||
expr.elements.forEach((prop, index) => {
|
||||
if (!(0, types_1.isStringLiteral)(prop)) {
|
||||
const code = (0, codegen_1.genBabelExpr)((0, types_1.arrayExpression)([(0, types_1.isSpreadElement)(prop) ? prop.argument : prop]));
|
||||
expr.elements[index] = (0, types_1.identifier)(rewriteStyleExpression((0, compiler_core_1.createSimpleExpression)(code.slice(1, -1), false), context).content);
|
||||
}
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
function rewriteStyleObjectExpression(expr, loc, context) {
|
||||
expr.properties.forEach((prop, index) => {
|
||||
if ((0, types_1.isSpreadElement)(prop)) {
|
||||
// <view :style="{...obj}"/>
|
||||
// <view style="{{a}}"/>
|
||||
const newExpr = (0, utils_1.rewriteSpreadElement)(runtimeHelpers_1.STRINGIFY_STYLE, prop, loc, context);
|
||||
if (newExpr) {
|
||||
prop.argument = newExpr;
|
||||
}
|
||||
}
|
||||
else if ((0, types_1.isObjectProperty)(prop)) {
|
||||
const { key, value, computed } = prop;
|
||||
if (!(0, types_1.isPrivateName)(key)) {
|
||||
if (computed) {
|
||||
// {[handle(computedKey)]:1} => {[a]:1}
|
||||
const newExpr = (0, utils_1.rewirteWithHelper)(runtimeHelpers_1.HYPHENATE, key, loc, context);
|
||||
if (newExpr) {
|
||||
prop.key = newExpr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// {fontSize:'15px'} => {'font-size':'15px'}
|
||||
prop.key = (0, ast_1.parseStringLiteral)(key);
|
||||
prop.key.value = (0, shared_1.hyphenate)(prop.key.value) + ':';
|
||||
}
|
||||
// {fontSize:`${fontSize}px`} => {'font-size':a}
|
||||
if ((0, utils_1.isStaticLiteral)(value)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
const newExpr = (0, utils_1.parseExprWithRewrite)((0, codegen_1.genBabelExpr)(value), loc, context, value);
|
||||
if (newExpr) {
|
||||
prop.value = newExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
function addSemicolon(expr) {
|
||||
return createBinaryExpression(expr, (0, types_1.stringLiteral)(';'));
|
||||
}
|
||||
function createBinaryExpression(left, right) {
|
||||
return (0, types_1.binaryExpression)('+', left, right);
|
||||
}
|
||||
function createStyleBindingByArrayExpression(expr) {
|
||||
let result;
|
||||
function concat(expr) {
|
||||
if (!result) {
|
||||
result = expr;
|
||||
}
|
||||
else {
|
||||
result = createBinaryExpression(addSemicolon(result), expr);
|
||||
}
|
||||
}
|
||||
expr.elements.forEach((prop) => {
|
||||
if ((0, types_1.isStringLiteral)(prop) || (0, types_1.isIdentifier)(prop)) {
|
||||
concat(prop);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function createStyleBindingByObjectExpression(expr) {
|
||||
let result;
|
||||
function concat(expr) {
|
||||
if (!result) {
|
||||
result = expr;
|
||||
}
|
||||
else {
|
||||
result = createBinaryExpression(addSemicolon(result), expr);
|
||||
}
|
||||
}
|
||||
expr.properties.forEach((prop) => {
|
||||
if ((0, types_1.isSpreadElement)(prop)) {
|
||||
concat(prop.argument);
|
||||
}
|
||||
else if ((0, types_1.isObjectProperty)(prop)) {
|
||||
const { key, value } = prop;
|
||||
if (!(0, types_1.isPrivateName)(key)) {
|
||||
const expr = createBinaryExpression((0, types_1.isStringLiteral)(key)
|
||||
? key // 之前已经补充了:
|
||||
: createBinaryExpression(key, (0, types_1.stringLiteral)(':')), value);
|
||||
concat(expr);
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformTag: NodeTransform;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformTag = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const transformTag = (node, _) => {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node) ||
|
||||
(_ && _.isCustomElement && _.isCustomElement(node.tag))) {
|
||||
return;
|
||||
}
|
||||
const newTag = uni_cli_shared_1.HTML_TO_MINI_PROGRAM_TAGS[node.tag];
|
||||
if (newTag) {
|
||||
node.tag = newTag;
|
||||
node.tagType = compiler_core_1.ElementTypes.ELEMENT;
|
||||
}
|
||||
};
|
||||
exports.transformTag = transformTag;
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import { type ElementNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function rewriteId(node: ElementNode, context: TransformContext): void;
|
||||
Generated
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.rewriteId = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const utils_1 = require("./utils");
|
||||
const transformSlot_1 = require("./transformSlot");
|
||||
const transformRef_1 = require("./transformRef");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const types_1 = require("@babel/types");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const builtInCustomElements = ['uni-cloud-db-element'];
|
||||
const builtInComponents = ['unicloud-db'];
|
||||
function rewriteId(node, context) {
|
||||
const isUniElement = !(0, uni_cli_shared_1.isUserComponent)(node, context);
|
||||
const origTagName = node.tag;
|
||||
const isBuiltInComponent = !isUniElement && builtInComponents.includes(origTagName);
|
||||
const userComponent = !(isUniElement || isBuiltInComponent);
|
||||
if (userComponent) {
|
||||
// TODO 目前不对用户的自定义组件支持 id 查询 UniElement
|
||||
// 后续要做的话,需要考虑自定义组件内部的单节点或多节点
|
||||
return;
|
||||
}
|
||||
const isBuiltInCustomElement = builtInCustomElements.includes(origTagName);
|
||||
if (isUniElement) {
|
||||
// 将内置的自定义元素转换为 view
|
||||
if (isBuiltInCustomElement) {
|
||||
node.props.unshift((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_ELEMENT_TAG, origTagName));
|
||||
node.tag = 'view';
|
||||
}
|
||||
}
|
||||
// 内置组件使用了 ref,没有 id 时,自动补充一个
|
||||
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
|
||||
let idProp = (0, compiler_core_1.findProp)(node, 'id');
|
||||
if (refProp && !idProp) {
|
||||
if (context.inVFor) {
|
||||
// v-for 中的 ref 需要使用 v-for 的 key 作为 id
|
||||
const keyAlias = (0, transformSlot_1.parseVForKeyAlias)(context);
|
||||
// 微信小程序元素id必须以字母开头,所以hashId不能放到前边,它可能是数字开头
|
||||
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId + '-';
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([`'${id}'+`, keyAlias.join(`+'-'+`)])));
|
||||
}
|
||||
else {
|
||||
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId;
|
||||
node.props.push((0, uni_cli_shared_1.createAttributeNode)('id', id));
|
||||
}
|
||||
}
|
||||
else if (refProp && idProp && (0, uni_cli_shared_1.isDirectiveNode)(idProp)) {
|
||||
// ref 和 id 都存在,且 id 是动态绑定的, 但是可能为空字符串。比如virtualHost绑定的id
|
||||
const idPropIndex = node.props.indexOf(idProp);
|
||||
node.props.splice(idPropIndex, 1);
|
||||
if (idProp.exp) {
|
||||
let idBindingExpr = (0, ast_1.parseExpr)(idProp.exp, context);
|
||||
let genId = '';
|
||||
if (context.inVFor) {
|
||||
// v-for 中的 ref 需要使用 v-for 的 key 作为 id
|
||||
const keyAlias = (0, transformSlot_1.parseVForKeyAlias)(context);
|
||||
// 微信小程序元素id必须以字母开头,所以hashId不能放到前边,它可能是数字开头
|
||||
genId =
|
||||
'r' +
|
||||
context.elementRefIndex++ +
|
||||
'-' +
|
||||
context.hashId +
|
||||
'-' +
|
||||
keyAlias.join('-');
|
||||
}
|
||||
else {
|
||||
genId = 'r' + context.elementRefIndex++ + '-' + context.hashId;
|
||||
}
|
||||
// TODO context.helperString能否避免调用?
|
||||
if ((0, types_1.isCallExpression)(idBindingExpr) &&
|
||||
(0, types_1.isIdentifier)(idBindingExpr.callee) &&
|
||||
idBindingExpr.callee.name === context.helperString(runtimeHelpers_1.GEN_UNI_ELEMENT_ID)) {
|
||||
// 如果调用的是genUniElementId,则直接传入自动生成的id作为第三个参数。此特性用于减小生成代码体积
|
||||
idBindingExpr.arguments.push((0, types_1.stringLiteral)(genId));
|
||||
}
|
||||
else {
|
||||
idBindingExpr = (0, types_1.conditionalExpression)((0, types_1.binaryExpression)('!==', idBindingExpr, (0, types_1.stringLiteral)('')), idBindingExpr, (0, types_1.stringLiteral)(genId));
|
||||
}
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(idBindingExpr))));
|
||||
}
|
||||
}
|
||||
idProp = (0, compiler_core_1.findProp)(node, 'id');
|
||||
if (!idProp) {
|
||||
return;
|
||||
}
|
||||
let idOptions = origTagName;
|
||||
if (isBuiltInComponent || isBuiltInCustomElement) {
|
||||
idOptions = {
|
||||
name: origTagName,
|
||||
type: isBuiltInComponent
|
||||
? 1 /* SetUniElementIdTagType.BuiltInComponent */
|
||||
: 2 /* SetUniElementIdTagType.BuiltInRootElement */,
|
||||
};
|
||||
}
|
||||
let idExprNode;
|
||||
// id="test" => :id="setUniElementId('test')"
|
||||
// 目前标签名有隐患,可能传入的是自定义组件名称
|
||||
if ((0, uni_cli_shared_1.isAttributeNode)(idProp)) {
|
||||
if (!idProp.value) {
|
||||
return;
|
||||
}
|
||||
idExprNode = `'${idProp.value.content}'`;
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_ELEMENT_ID, (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
|
||||
idExprNode,
|
||||
',',
|
||||
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
|
||||
parseUniElementRefCode(node, context),
|
||||
')',
|
||||
])));
|
||||
}
|
||||
else if (idProp.exp) {
|
||||
idExprNode = idProp.exp;
|
||||
const idPropIndex = node.props.indexOf(idProp);
|
||||
// :id="a" => :id="setUniElementId(a)"
|
||||
node.props.splice(idPropIndex, 1, (0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
|
||||
idExprNode,
|
||||
',',
|
||||
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
|
||||
parseUniElementRefCode(node, context),
|
||||
')',
|
||||
])));
|
||||
}
|
||||
if (context.miniProgram.filter?.setStyle) {
|
||||
// 支持通过filter来设置style
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)((0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_STYLE), (0, utils_1.filterName)(utils_1.FILTER_SET_ELEMENT_STYLE)));
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_SET_ELEMENT_STYLE, ''));
|
||||
// setAnimation
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)((0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_ANIMATION), (0, utils_1.filterName)(utils_1.FILTER_SET_ELEMENT_ANIMATION)));
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_SET_ELEMENT_ANIMATION, ''));
|
||||
if (!context.autoImportFilters.find((filter) => filter.name === utils_1.FILTER_MODULE_NAME)) {
|
||||
context.autoImportFilters.push({
|
||||
name: utils_1.FILTER_MODULE_NAME,
|
||||
id: utils_1.FILTER_MODULE_FILE_NAME,
|
||||
type: 'filter',
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 如果没有动态绑定 style,则创建一个新的
|
||||
const styleProp = (0, compiler_core_1.findProp)(node, 'style', true, true);
|
||||
if (!styleProp) {
|
||||
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('style', (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
|
||||
idExprNode,
|
||||
')',
|
||||
])));
|
||||
}
|
||||
else {
|
||||
// 传递已绑定的 style
|
||||
styleProp.exp = (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
|
||||
idExprNode,
|
||||
',',
|
||||
styleProp.exp,
|
||||
')',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.rewriteId = rewriteId;
|
||||
function parseUniElementRefCode(node, context) {
|
||||
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
|
||||
if (!refProp) {
|
||||
return '';
|
||||
}
|
||||
const { code, refKey } = (0, transformRef_1.parseRefCode)(refProp, context);
|
||||
const opts = {};
|
||||
if (refKey) {
|
||||
opts.k = refKey;
|
||||
}
|
||||
if (context.inVFor) {
|
||||
opts.f = 1;
|
||||
}
|
||||
const children = [',', code];
|
||||
if (Object.keys(opts).length) {
|
||||
children.push(',', JSON.stringify(opts));
|
||||
}
|
||||
return (0, compiler_core_1.createCompoundExpression)(children);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { type Expression, type Identifier, type MemberExpression, type Node, type SpreadElement } from '@babel/types';
|
||||
import { type ElementNode, type ExpressionNode, type SimpleExpressionNode, type SourceLocation, type TransformContext as VueTransformContext } from '@vue/compiler-core';
|
||||
import type { CodegenScope } from '../options';
|
||||
import { type TransformContext } from '../transform';
|
||||
export declare const ATTR_VUE_ID = "u-i";
|
||||
export declare const ATTR_VUE_SLOTS = "u-s";
|
||||
export declare const ATTR_VUE_PROPS = "u-p";
|
||||
export declare const ATTR_VUE_REF: string;
|
||||
export declare const ATTR_VUE_REF_IN_FOR: string;
|
||||
export declare const ATTR_COM_TYPE = "u-t";
|
||||
export declare const ATTR_ELEMENT_ID = "u-e";
|
||||
export declare const ATTR_ELEMENT_TAG = "u-t";
|
||||
export declare const ATTR_SET_ELEMENT_STYLE = "eS";
|
||||
export declare const ATTR_SET_ELEMENT_ANIMATION = "eA";
|
||||
export declare const FILTER_MODULE_NAME = "uV";
|
||||
export declare const FILTER_MODULE_FILE_NAME = "uniView";
|
||||
export declare const FILTER_SET_ELEMENT_STYLE = "sS";
|
||||
export declare const FILTER_SET_ELEMENT_ANIMATION = "sA";
|
||||
export declare const SCOPED_SLOT_IDENTIFIER = "__SCOPED_SLOT__";
|
||||
export declare function filterObserverName(name: string): string;
|
||||
export declare function filterName(name: string): string;
|
||||
export declare function rewriteSpreadElement(name: symbol, expr: SpreadElement, loc: SourceLocation, context: TransformContext): Identifier | MemberExpression | undefined;
|
||||
export declare function rewirteWithHelper(name: symbol, expr: Expression, loc: SourceLocation, context: TransformContext): Identifier | MemberExpression | undefined;
|
||||
export declare function parseExprWithRewrite(code: string, loc: SourceLocation, context: TransformContext, node?: Expression): Identifier | MemberExpression | undefined;
|
||||
export declare function parseExprWithRewriteClass(code: string, loc: SourceLocation, context: TransformContext, node: Expression): Identifier | MemberExpression | undefined;
|
||||
export declare function rewriteExpressionWithoutProperty(node: ExpressionNode, context: TransformContext, babelNode?: Expression, scope?: CodegenScope): SimpleExpressionNode;
|
||||
export declare function rewriteExpression(node: ExpressionNode, context: TransformContext | VueTransformContext, babelNode?: Expression, scope?: CodegenScope, { property, ignoreLiteral, referencedScope, }?: {
|
||||
property: boolean;
|
||||
ignoreLiteral: boolean;
|
||||
referencedScope?: CodegenScope;
|
||||
}): SimpleExpressionNode;
|
||||
export declare function findReferencedScope(node: Expression, scope: CodegenScope, findReferenced?: boolean): CodegenScope;
|
||||
export declare function isReferencedByIds(node: Expression, knownIds: string[]): boolean;
|
||||
export declare function isStaticLiteral(value: Node | null | undefined): boolean;
|
||||
export declare function removeAttribute(node: ElementNode, name: string): void;
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.removeAttribute = exports.isStaticLiteral = exports.isReferencedByIds = exports.findReferencedScope = exports.rewriteExpression = exports.rewriteExpressionWithoutProperty = exports.parseExprWithRewriteClass = exports.parseExprWithRewrite = exports.rewirteWithHelper = exports.rewriteSpreadElement = exports.filterName = exports.filterObserverName = exports.SCOPED_SLOT_IDENTIFIER = exports.FILTER_SET_ELEMENT_ANIMATION = exports.FILTER_SET_ELEMENT_STYLE = exports.FILTER_MODULE_FILE_NAME = exports.FILTER_MODULE_NAME = exports.ATTR_SET_ELEMENT_ANIMATION = exports.ATTR_SET_ELEMENT_STYLE = exports.ATTR_ELEMENT_TAG = exports.ATTR_ELEMENT_ID = exports.ATTR_COM_TYPE = exports.ATTR_VUE_REF_IN_FOR = exports.ATTR_VUE_REF = exports.ATTR_VUE_PROPS = exports.ATTR_VUE_SLOTS = exports.ATTR_VUE_ID = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const estree_walker_1 = require("estree-walker");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const transform_1 = require("../transform");
|
||||
// v-i,v-s 不能在 quickapp-webview 中使用,估计是内部处理成了指令之类的
|
||||
exports.ATTR_VUE_ID = 'u-i';
|
||||
exports.ATTR_VUE_SLOTS = 'u-s';
|
||||
exports.ATTR_VUE_PROPS = 'u-p';
|
||||
exports.ATTR_VUE_REF = 'u-' + uni_cli_shared_1.VUE_REF;
|
||||
exports.ATTR_VUE_REF_IN_FOR = 'u-' + uni_cli_shared_1.VUE_REF_IN_FOR;
|
||||
exports.ATTR_COM_TYPE = 'u-t';
|
||||
exports.ATTR_ELEMENT_ID = 'u-e';
|
||||
exports.ATTR_ELEMENT_TAG = 'u-t';
|
||||
exports.ATTR_SET_ELEMENT_STYLE = 'eS'; // 不能使用连字符e-s
|
||||
exports.ATTR_SET_ELEMENT_ANIMATION = 'eA'; // 不能使用连字符e-a
|
||||
exports.FILTER_MODULE_NAME = 'uV'; // uniView
|
||||
exports.FILTER_MODULE_FILE_NAME = 'uniView';
|
||||
exports.FILTER_SET_ELEMENT_STYLE = 'sS'; // setStyle
|
||||
exports.FILTER_SET_ELEMENT_ANIMATION = 'sA'; // setAnimation
|
||||
exports.SCOPED_SLOT_IDENTIFIER = '__SCOPED_SLOT__';
|
||||
function filterObserverName(name) {
|
||||
return 'change:' + name;
|
||||
}
|
||||
exports.filterObserverName = filterObserverName;
|
||||
function filterName(name) {
|
||||
return exports.FILTER_MODULE_NAME + '.' + name;
|
||||
}
|
||||
exports.filterName = filterName;
|
||||
function rewriteSpreadElement(name, expr, loc, context) {
|
||||
return rewirteWithHelper(name, expr.argument, loc, context);
|
||||
}
|
||||
exports.rewriteSpreadElement = rewriteSpreadElement;
|
||||
function rewirteWithHelper(name, expr, loc, context) {
|
||||
return parseExprWithRewrite(context.helperString(name) + '(' + (0, codegen_1.genBabelExpr)(expr) + ')', loc, context);
|
||||
}
|
||||
exports.rewirteWithHelper = rewirteWithHelper;
|
||||
function parseExprWithRewrite(code, loc, context, node) {
|
||||
return (0, ast_1.parseExpr)(rewriteExpression((0, compiler_core_1.createSimpleExpression)(code, false, loc), context, node), context);
|
||||
}
|
||||
exports.parseExprWithRewrite = parseExprWithRewrite;
|
||||
function parseExprWithRewriteClass(code, loc, context, node) {
|
||||
// a?1:0
|
||||
return (0, ast_1.parseExpr)(rewriteExpression((0, compiler_core_1.createSimpleExpression)(code, false, loc), context, !(0, ast_1.isUndefined)(node)
|
||||
? (0, types_1.conditionalExpression)(node, (0, types_1.numericLiteral)(1), (0, types_1.stringLiteral)(''))
|
||||
: node), context);
|
||||
}
|
||||
exports.parseExprWithRewriteClass = parseExprWithRewriteClass;
|
||||
function rewriteExpressionWithoutProperty(node, context, babelNode, scope = context.currentScope) {
|
||||
return rewriteExpression(node, context, babelNode, scope, {
|
||||
property: false,
|
||||
ignoreLiteral: false,
|
||||
});
|
||||
}
|
||||
exports.rewriteExpressionWithoutProperty = rewriteExpressionWithoutProperty;
|
||||
function rewriteExpression(node, context, babelNode, scope = context.currentScope, { property, ignoreLiteral, referencedScope, } = {
|
||||
property: true,
|
||||
ignoreLiteral: false,
|
||||
}) {
|
||||
if (node.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && node.isStatic) {
|
||||
return node;
|
||||
}
|
||||
if (!babelNode) {
|
||||
const code = (0, codegen_1.genExpr)(node);
|
||||
babelNode = (0, ast_1.parseExpr)(code, context, node);
|
||||
if (!babelNode) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(code);
|
||||
}
|
||||
}
|
||||
if (!ignoreLiteral && isStaticLiteral(babelNode)) {
|
||||
return node;
|
||||
}
|
||||
if ((0, ast_1.isUndefined)(babelNode)) {
|
||||
return (0, compiler_core_1.createSimpleExpression)('undefined', false, node.loc);
|
||||
}
|
||||
// wxs 等表达式
|
||||
if (context.filters?.length) {
|
||||
if (isReferencedByIds(babelNode, context.filters)) {
|
||||
return (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genExpr)(node), false, node.loc);
|
||||
}
|
||||
}
|
||||
referencedScope = referencedScope || findReferencedScope(babelNode, scope);
|
||||
const id = referencedScope.id.next();
|
||||
if (property) {
|
||||
referencedScope.properties.push((0, types_1.objectProperty)((0, types_1.identifier)(id), babelNode));
|
||||
}
|
||||
// 在 v-for 中包含的 v-if 块,所有变量需要补充当前 v-for value 前缀
|
||||
if ((0, transform_1.isVIfScope)(referencedScope)) {
|
||||
if ((0, transform_1.isVForScope)(referencedScope.parentScope)) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(referencedScope.parentScope.valueAlias + '.' + id);
|
||||
}
|
||||
return (0, compiler_core_1.createSimpleExpression)(id);
|
||||
}
|
||||
else if ((0, transform_1.isVForScope)(referencedScope)) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(referencedScope.valueAlias + '.' + id);
|
||||
}
|
||||
return (0, compiler_core_1.createSimpleExpression)(id);
|
||||
}
|
||||
exports.rewriteExpression = rewriteExpression;
|
||||
function findReferencedScope(node, scope, findReferenced = true) {
|
||||
if ((0, transform_1.isVIfScope)(scope)) {
|
||||
return scope;
|
||||
}
|
||||
else if ((0, transform_1.isVForScope)(scope)) {
|
||||
if (!findReferenced) {
|
||||
return scope;
|
||||
}
|
||||
if (isReferencedByIds(node, scope.locals)) {
|
||||
return scope;
|
||||
}
|
||||
return findReferencedScope(node, scope.parent, findReferenced);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
exports.findReferencedScope = findReferencedScope;
|
||||
function isReferencedByIds(node, knownIds) {
|
||||
let referenced = false;
|
||||
(0, estree_walker_1.walk)(node, {
|
||||
enter(node, parent) {
|
||||
if (referenced) {
|
||||
return this.skip();
|
||||
}
|
||||
if (!(0, types_1.isIdentifier)(node)) {
|
||||
return;
|
||||
}
|
||||
if (knownIds.includes(node.name) &&
|
||||
(!parent || (0, types_1.isReferenced)(node, parent))) {
|
||||
referenced = true;
|
||||
return this.skip();
|
||||
}
|
||||
},
|
||||
});
|
||||
return referenced;
|
||||
}
|
||||
exports.isReferencedByIds = isReferencedByIds;
|
||||
function isStaticLiteral(value) {
|
||||
return (0, types_1.isLiteral)(value) && !(0, types_1.isTemplateLiteral)(value);
|
||||
}
|
||||
exports.isStaticLiteral = isStaticLiteral;
|
||||
function removeAttribute(node, name) {
|
||||
const index = node.props.findIndex((prop) => prop.name === name);
|
||||
if (index > -1) {
|
||||
node.props.splice(index, 1);
|
||||
}
|
||||
}
|
||||
exports.removeAttribute = removeAttribute;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { DirectiveTransform } from '../transform';
|
||||
export declare const transformBind: DirectiveTransform;
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformBind = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
const transformBind = (dir, _node, context) => {
|
||||
const { exp, modifiers, loc } = dir;
|
||||
const arg = dir.arg;
|
||||
if (arg.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
arg.children.unshift(`(`);
|
||||
arg.children.push(`) || ""`);
|
||||
}
|
||||
else if (!arg.isStatic) {
|
||||
arg.content = `${arg.content} || ""`;
|
||||
}
|
||||
// .sync is replaced by v-model:arg
|
||||
if (modifiers.includes('camel')) {
|
||||
if (arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (arg.isStatic) {
|
||||
arg.content = (0, shared_1.camelize)(arg.content);
|
||||
}
|
||||
else {
|
||||
// arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`
|
||||
}
|
||||
}
|
||||
else {
|
||||
// arg.children.unshift(`${context.helperString(CAMELIZE)}(`)
|
||||
// arg.children.push(`)`)
|
||||
}
|
||||
}
|
||||
if (modifiers.includes('prop')) {
|
||||
context[context.isX ? 'onError' : 'onWarn']((0, errors_1.createMPCompilerError)(4 /* MPErrorCodes.X_V_BIND_MODIFIER_PROP */, loc));
|
||||
}
|
||||
if (modifiers.includes('attr')) {
|
||||
context[context.isX ? 'onError' : 'onWarn']((0, errors_1.createMPCompilerError)(5 /* MPErrorCodes.X_V_BIND_MODIFIER_ATTR */, loc));
|
||||
}
|
||||
if (!exp ||
|
||||
(exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_BIND_NO_EXPRESSION, loc));
|
||||
return {
|
||||
props: [(0, compiler_core_1.createObjectProperty)(arg, (0, compiler_core_1.createSimpleExpression)('', true, loc))],
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: [(0, compiler_core_1.createObjectProperty)(arg, exp)],
|
||||
};
|
||||
};
|
||||
exports.transformBind = transformBind;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { type ElementNode, ElementTypes, type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
import { type NodeTransform, type TransformContext } from '../transform';
|
||||
import { type Expression, type Identifier, type Pattern, type RestElement } from '@babel/types';
|
||||
import type { CodegenScope, CodegenVForScope } from '../options';
|
||||
export type VForOptions = Omit<ForParseResult, 'tagType'> & {
|
||||
sourceExpr?: Expression;
|
||||
sourceAlias: string;
|
||||
sourceCode: string;
|
||||
valueCode: string;
|
||||
valueExpr: Identifier | Pattern | RestElement;
|
||||
valueAlias: string;
|
||||
keyCode: string;
|
||||
keyExpr: Identifier | Pattern | RestElement;
|
||||
keyAlias: string;
|
||||
indexCode: string;
|
||||
indexExpr: Identifier | Pattern | RestElement;
|
||||
indexAlias: string;
|
||||
node: ElementNode;
|
||||
};
|
||||
export type ForElementNode = ElementNode & {
|
||||
vFor: VForOptions & {
|
||||
source: ExpressionNode;
|
||||
};
|
||||
};
|
||||
export declare function isForElementNode(node: unknown): node is ForElementNode;
|
||||
export declare const transformFor: NodeTransform;
|
||||
export declare function parseVForScope(currentScope: CodegenScope): CodegenVForScope | undefined;
|
||||
export interface ForParseResult {
|
||||
source: ExpressionNode;
|
||||
value: ExpressionNode;
|
||||
key: ExpressionNode;
|
||||
index: ExpressionNode;
|
||||
tagType: ElementTypes;
|
||||
}
|
||||
export declare function parseForExpression(input: SimpleExpressionNode, context: TransformContext): ForParseResult | undefined;
|
||||
export declare function createForLoopParams({ value, key, index }: ForParseResult, memoArgs?: ExpressionNode[]): ExpressionNode[];
|
||||
export declare function createVForArrowFunctionExpression({ valueExpr, keyExpr, indexExpr, properties, }: CodegenVForScope): import("@babel/types").ArrowFunctionExpression;
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVForArrowFunctionExpression = exports.createForLoopParams = exports.parseForExpression = exports.parseVForScope = exports.transformFor = exports.isForElementNode = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const ast_1 = require("../ast");
|
||||
const transform_1 = require("../transform");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
const codegen_1 = require("../codegen");
|
||||
const types_1 = require("@babel/types");
|
||||
const utils_1 = require("./utils");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const vSlot_1 = require("./vSlot");
|
||||
function isForElementNode(node) {
|
||||
return !!node.vFor;
|
||||
}
|
||||
exports.isForElementNode = isForElementNode;
|
||||
exports.transformFor = (0, transform_1.createStructuralDirectiveTransform)('for', (node, dir, context) => {
|
||||
if (!dir.exp) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc));
|
||||
return;
|
||||
}
|
||||
const parseResult = parseForExpression(dir.exp, context);
|
||||
if (!parseResult) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc));
|
||||
return;
|
||||
}
|
||||
parseResult.tagType = node.tagType;
|
||||
const { addIdentifiers, removeIdentifiers } = context;
|
||||
const { source, value, key, index } = parseResult;
|
||||
if (context.prefixIdentifiers) {
|
||||
addIdentifiers(value);
|
||||
addIdentifiers(key);
|
||||
addIdentifiers(index);
|
||||
}
|
||||
const { currentScope: parentScope, scopes, popScope } = context;
|
||||
const sourceExpr = (0, ast_1.parseExpr)(source, context);
|
||||
const valueCode = (0, codegen_1.genExpr)(value);
|
||||
const valueExpr = (0, ast_1.parseParam)(valueCode, context, value);
|
||||
const valueAlias = parseAlias(valueExpr, valueCode, 'v' + scopes.vFor);
|
||||
const keyCode = (0, codegen_1.genExpr)(key);
|
||||
const keyExpr = (0, ast_1.parseParam)(keyCode, context, key);
|
||||
const keyAlias = parseAlias(keyExpr, keyCode, 'k' + scopes.vFor);
|
||||
const indexCode = (0, codegen_1.genExpr)(index);
|
||||
const indexExpr = (0, ast_1.parseParam)(indexCode, context, index);
|
||||
const indexAlias = parseAlias(indexExpr, indexCode, 'i' + scopes.vFor);
|
||||
// 先占位 vFor,后续更新 cloneSourceExpr 为 CallExpression
|
||||
const cloneSourceExpr = (0, types_1.cloneNode)(sourceExpr, false);
|
||||
const sourceAliasReferencedScope = (0, utils_1.findReferencedScope)(cloneSourceExpr, context.currentScope,
|
||||
// vFor 嵌套时,始终保持嵌套关系,issues/3263
|
||||
false);
|
||||
// 寻找子节点中 if 指令作用域
|
||||
const vIfReferencedScope = findVIfReferencedScope(node, context.currentScope, context);
|
||||
// 取最近的作用域
|
||||
const referencedScope = vIfReferencedScope &&
|
||||
context.getScopeIndex(vIfReferencedScope) >
|
||||
context.getScopeIndex(sourceAliasReferencedScope)
|
||||
? vIfReferencedScope
|
||||
: sourceAliasReferencedScope;
|
||||
const sourceAlias = (0, utils_1.rewriteExpression)(source, context, cloneSourceExpr, parentScope,
|
||||
// 强制 rewrite,因为即使是字符串,数字,也要走 vFor 函数
|
||||
{
|
||||
property: true,
|
||||
ignoreLiteral: true,
|
||||
referencedScope,
|
||||
}).content;
|
||||
const sourceCode = `{{${sourceAlias}}}`;
|
||||
const vForData = {
|
||||
source,
|
||||
sourceExpr,
|
||||
sourceAlias,
|
||||
sourceCode,
|
||||
value,
|
||||
valueCode,
|
||||
valueExpr,
|
||||
valueAlias,
|
||||
key,
|
||||
keyCode,
|
||||
keyExpr,
|
||||
keyAlias,
|
||||
index,
|
||||
indexCode,
|
||||
indexExpr,
|
||||
indexAlias,
|
||||
node,
|
||||
};
|
||||
const vForScope = context.addVForScope({
|
||||
...vForData,
|
||||
locals: findVForLocals(parseResult),
|
||||
});
|
||||
const vFor = {
|
||||
...vForData,
|
||||
};
|
||||
const isScopedSlot = (0, transform_1.isScopedSlotVFor)(vForScope);
|
||||
node.vFor = vFor;
|
||||
scopes.vFor++;
|
||||
return () => {
|
||||
scopes.vFor--;
|
||||
if ((0, compiler_core_1.isTemplateNode)(node)) {
|
||||
node.children.some((c) => {
|
||||
if (c.type === compiler_core_1.NodeTypes.ELEMENT && !isForElementNode(c)) {
|
||||
const key = (0, compiler_core_1.findProp)(c, 'key');
|
||||
if (key) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT, key.loc));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (context.prefixIdentifiers) {
|
||||
value && removeIdentifiers(value);
|
||||
key && removeIdentifiers(key);
|
||||
index && removeIdentifiers(index);
|
||||
}
|
||||
(0, shared_1.extend)(clearExpr(cloneSourceExpr), isScopedSlot
|
||||
? (0, vSlot_1.createVSlotCallExpression)(node
|
||||
.slotComponent, vForScope, context)
|
||||
: createVForCallExpression(vForScope, context));
|
||||
popScope();
|
||||
};
|
||||
});
|
||||
function clearExpr(expr) {
|
||||
Object.keys(expr).forEach((key) => {
|
||||
delete expr[key];
|
||||
});
|
||||
return expr;
|
||||
}
|
||||
function parseAlias(babelExpr, exprCode, fallback) {
|
||||
if ((0, types_1.isIdentifier)(babelExpr)) {
|
||||
return exprCode;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
function parseVForScope(currentScope) {
|
||||
while (currentScope) {
|
||||
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
|
||||
return currentScope;
|
||||
}
|
||||
currentScope = currentScope.parent;
|
||||
}
|
||||
}
|
||||
exports.parseVForScope = parseVForScope;
|
||||
function findVIfReferencedScope(node, currentScope, context) {
|
||||
if (!currentScope) {
|
||||
return;
|
||||
}
|
||||
const vForScope = parseVForScope(currentScope);
|
||||
if (!vForScope) {
|
||||
return;
|
||||
}
|
||||
if (!node.children.find((item) => checkVIfReferenced(item, vForScope, context))) {
|
||||
return findVIfReferencedScope(node, currentScope.parent, context);
|
||||
}
|
||||
return vForScope;
|
||||
}
|
||||
function checkVIfReferenced(node, vForScope, context) {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return false;
|
||||
}
|
||||
// 嵌套 for 不查找
|
||||
if ((0, compiler_core_1.findDir)(node, 'for')) {
|
||||
return false;
|
||||
}
|
||||
const ifDir = (0, compiler_core_1.findDir)(node, 'if');
|
||||
if (ifDir) {
|
||||
return checkDirReferenced(ifDir.exp, vForScope, context);
|
||||
}
|
||||
const elseIfDir = (0, compiler_core_1.findDir)(node, 'else-if');
|
||||
if (elseIfDir) {
|
||||
return checkDirReferenced(elseIfDir.exp, vForScope, context);
|
||||
}
|
||||
return !!node.children.find((item) => checkVIfReferenced(item, vForScope, context));
|
||||
}
|
||||
function checkDirReferenced(node, vForScope, context) {
|
||||
if (node) {
|
||||
const babelNode = (0, ast_1.parseExpr)(node, context);
|
||||
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, vForScope.locals)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function findVForLocals({ value, key, index }) {
|
||||
const ids = [];
|
||||
if (value) {
|
||||
findIds(value, ids);
|
||||
}
|
||||
if (key) {
|
||||
findIds(key, ids);
|
||||
}
|
||||
if (index) {
|
||||
findIds(index, ids);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
function findIds(exp, ids) {
|
||||
if ((0, shared_1.isString)(exp)) {
|
||||
ids.push(exp);
|
||||
}
|
||||
else if (exp.identifiers) {
|
||||
exp.identifiers.forEach((id) => ids.push(id));
|
||||
}
|
||||
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
ids.push(exp.content);
|
||||
}
|
||||
}
|
||||
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
|
||||
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
|
||||
const stripParensRE = /^\(|\)$/g;
|
||||
function parseForExpression(input, context) {
|
||||
const loc = input.loc;
|
||||
const exp = input.content;
|
||||
const inMatch = exp.match(forAliasRE);
|
||||
if (!inMatch)
|
||||
return;
|
||||
const [, LHS, RHS] = inMatch;
|
||||
const result = {
|
||||
source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),
|
||||
value: (0, compiler_core_1.createSimpleExpression)('v' + context.scopes.vFor),
|
||||
key: (0, compiler_core_1.createSimpleExpression)('k' + context.scopes.vFor),
|
||||
index: (0, compiler_core_1.createSimpleExpression)('i' + context.scopes.vFor),
|
||||
tagType: compiler_core_1.ElementTypes.ELEMENT,
|
||||
};
|
||||
if (context.prefixIdentifiers) {
|
||||
result.source = (0, transformExpression_1.processExpression)(result.source, context);
|
||||
}
|
||||
let valueContent = LHS.trim().replace(stripParensRE, '').trim();
|
||||
const trimmedOffset = LHS.indexOf(valueContent);
|
||||
const iteratorMatch = valueContent.match(forIteratorRE);
|
||||
if (iteratorMatch) {
|
||||
valueContent = valueContent.replace(forIteratorRE, '').trim();
|
||||
const keyContent = iteratorMatch[1].trim();
|
||||
let keyOffset;
|
||||
if (keyContent) {
|
||||
keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);
|
||||
result.key = createAliasExpression(loc, keyContent, keyOffset);
|
||||
if (context.prefixIdentifiers) {
|
||||
result.key = (0, transformExpression_1.processExpression)(result.key, context, true);
|
||||
}
|
||||
}
|
||||
if (iteratorMatch[2]) {
|
||||
const indexContent = iteratorMatch[2].trim();
|
||||
if (indexContent) {
|
||||
result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key
|
||||
? keyOffset + keyContent.length
|
||||
: trimmedOffset + valueContent.length));
|
||||
if (context.prefixIdentifiers) {
|
||||
result.index = (0, transformExpression_1.processExpression)(result.index, context, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valueContent) {
|
||||
result.value = createAliasExpression(loc, valueContent, trimmedOffset);
|
||||
if (context.prefixIdentifiers) {
|
||||
result.value = (0, transformExpression_1.processExpression)(result.value, context, true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.parseForExpression = parseForExpression;
|
||||
function createAliasExpression(range, content, offset) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(content, false, (0, uni_cli_shared_1.getInnerRange)(range, offset, content.length));
|
||||
}
|
||||
function createForLoopParams({ value, key, index }, memoArgs = []) {
|
||||
return createParamsList([value, key, index, ...memoArgs]);
|
||||
}
|
||||
exports.createForLoopParams = createForLoopParams;
|
||||
function createParamsList(args) {
|
||||
let i = args.length;
|
||||
while (i--) {
|
||||
if (args[i])
|
||||
break;
|
||||
}
|
||||
return args
|
||||
.slice(0, i + 1)
|
||||
.map((arg, i) => arg || (0, compiler_core_1.createSimpleExpression)(`_`.repeat(i + 1), false));
|
||||
}
|
||||
function createVForCallExpression(vForScope, context) {
|
||||
// let sourceExpr: Expression = vForScope.sourceExpr!
|
||||
// if (isNumericLiteral(sourceExpr)) {
|
||||
// sourceExpr = numericLiteralToArrayExpr((sourceExpr as NumericLiteral).value)
|
||||
// }
|
||||
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.V_FOR)), [
|
||||
vForScope.sourceExpr,
|
||||
createVForArrowFunctionExpression(vForScope),
|
||||
]);
|
||||
}
|
||||
function createVForArrowFunctionExpression({ valueExpr, keyExpr, indexExpr, properties, }) {
|
||||
const params = [];
|
||||
if (valueExpr) {
|
||||
params.push(valueExpr);
|
||||
}
|
||||
if (keyExpr) {
|
||||
params.push(keyExpr);
|
||||
}
|
||||
if (indexExpr) {
|
||||
params.push(indexExpr);
|
||||
}
|
||||
return (0, types_1.arrowFunctionExpression)(params, (0, types_1.blockStatement)([(0, types_1.returnStatement)((0, types_1.objectExpression)(properties))]));
|
||||
}
|
||||
exports.createVForArrowFunctionExpression = createVForArrowFunctionExpression;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformHtml: NodeTransform;
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformHtml = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const transformHtml = (node, _) => {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return;
|
||||
}
|
||||
const dir = (0, compiler_core_1.findDir)(node, 'html');
|
||||
if (!dir) {
|
||||
return;
|
||||
}
|
||||
// remove v-html
|
||||
node.props.splice(node.props.indexOf(dir), 1);
|
||||
if (node.tagType !== compiler_core_1.ElementTypes.ELEMENT) {
|
||||
return;
|
||||
}
|
||||
node.isSelfClosing = false;
|
||||
node.children = [createRichText(node, dir)];
|
||||
};
|
||||
exports.transformHtml = transformHtml;
|
||||
function createRichText(node, dir) {
|
||||
return {
|
||||
tag: 'rich-text',
|
||||
type: compiler_core_1.NodeTypes.ELEMENT,
|
||||
tagType: compiler_core_1.ElementTypes.ELEMENT,
|
||||
props: [(0, uni_cli_shared_1.createBindDirectiveNode)('nodes', dir.exp || '')],
|
||||
isSelfClosing: true,
|
||||
children: [],
|
||||
codegenNode: undefined,
|
||||
ns: node.ns,
|
||||
loc: node.loc,
|
||||
};
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { type DirectiveNode, type ElementNode, type IfNode } from '@vue/compiler-core';
|
||||
import { type NodeTransform, type TransformContext } from '../transform';
|
||||
interface IfOptions {
|
||||
name: string;
|
||||
condition?: string;
|
||||
}
|
||||
export type IfElementNode = ElementNode & {
|
||||
vIf: IfOptions;
|
||||
};
|
||||
export declare function isIfElementNode(node: unknown): node is IfElementNode;
|
||||
export declare const transformIf: NodeTransform;
|
||||
export declare function processIf(node: ElementNode, dir: DirectiveNode, context: TransformContext, processCodegen?: (node: IfNode, branch: IfElementNode, isRoot: boolean) => (() => void) | undefined): (() => void) | undefined;
|
||||
export {};
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processIf = exports.transformIf = exports.isIfElementNode = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const ast_1 = require("../ast");
|
||||
const transform_1 = require("../transform");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
const utils_1 = require("./utils");
|
||||
function isIfElementNode(node) {
|
||||
return !!node.vIf;
|
||||
}
|
||||
exports.isIfElementNode = isIfElementNode;
|
||||
exports.transformIf = (0, transform_1.createStructuralDirectiveTransform)(/^(if|else|else-if)$/, (node, dir, context) => {
|
||||
return processIf(node, dir, context, (ifNode, branch, isRoot) => {
|
||||
const { currentScope: parentScope, popScope } = context;
|
||||
const ifOptions = {
|
||||
name: dir.name,
|
||||
};
|
||||
branch.vIf = ifOptions;
|
||||
const condition = dir.exp ? (0, ast_1.parseExpr)(dir.exp, context) : undefined;
|
||||
const vIfScope = context.addVIfScope({
|
||||
name: dir.name,
|
||||
condition,
|
||||
});
|
||||
if (condition) {
|
||||
if (!(0, utils_1.isStaticLiteral)(condition)) {
|
||||
ifOptions.condition = (0, utils_1.rewriteExpression)(dir.exp, context, condition, parentScope).content;
|
||||
}
|
||||
else {
|
||||
ifOptions.condition = dir.exp.content;
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
if (isRoot) {
|
||||
parentScope.properties.push((0, ast_1.createVIfSpreadElement)(vIfScope));
|
||||
}
|
||||
else {
|
||||
const vIfSpreadElement = findVIfSpreadElement(parentScope);
|
||||
if (!vIfSpreadElement) {
|
||||
popScope();
|
||||
return context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
|
||||
}
|
||||
let alternate = (0, ast_1.createObjectExpression)([]);
|
||||
if (dir.name === 'else-if') {
|
||||
alternate = (0, ast_1.createVIfConditionalExpression)(vIfScope);
|
||||
}
|
||||
else if (dir.name === 'else') {
|
||||
alternate = (0, ast_1.createObjectExpression)(vIfScope.properties);
|
||||
}
|
||||
findVIfConditionalExpression(vIfSpreadElement.argument).alternate = alternate;
|
||||
}
|
||||
popScope();
|
||||
};
|
||||
});
|
||||
});
|
||||
function processIf(node, dir, context, processCodegen) {
|
||||
if (dir.name !== 'else' &&
|
||||
(!dir.exp || !dir.exp.content.trim())) {
|
||||
const loc = dir.exp ? dir.exp.loc : node.loc;
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc));
|
||||
dir.exp = (0, compiler_core_1.createSimpleExpression)(`true`, false, loc);
|
||||
}
|
||||
if (context.prefixIdentifiers && dir.exp) {
|
||||
// dir.exp can only be simple expression because vIf transform is applied
|
||||
// before expression transform.
|
||||
dir.exp = (0, transformExpression_1.processExpression)(dir.exp, context);
|
||||
}
|
||||
if (dir.name === 'if') {
|
||||
const ifNode = {
|
||||
type: compiler_core_1.NodeTypes.IF,
|
||||
loc: node.loc,
|
||||
branches: [node],
|
||||
};
|
||||
context.replaceNode(ifNode);
|
||||
if (processCodegen) {
|
||||
return processCodegen(ifNode, node, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// locate the adjacent v-if
|
||||
const siblings = context.parent.children;
|
||||
let i = siblings.indexOf(node);
|
||||
while (i-- >= -1) {
|
||||
const sibling = siblings[i];
|
||||
if (sibling && sibling.type === compiler_core_1.NodeTypes.COMMENT) {
|
||||
context.removeNode(sibling);
|
||||
continue;
|
||||
}
|
||||
if (sibling &&
|
||||
sibling.type === compiler_core_1.NodeTypes.TEXT &&
|
||||
!sibling.content.trim().length) {
|
||||
context.removeNode(sibling);
|
||||
continue;
|
||||
}
|
||||
if (sibling && sibling.type === compiler_core_1.NodeTypes.IF) {
|
||||
// Check if v-else was followed by v-else-if
|
||||
if (dir.name === 'else-if' &&
|
||||
sibling.branches[sibling.branches.length - 1].vIf.condition === undefined) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
|
||||
}
|
||||
// move the node to the if node's branches
|
||||
context.removeNode();
|
||||
sibling.branches.push(node);
|
||||
const onExit = processCodegen &&
|
||||
processCodegen(sibling, node, false);
|
||||
// since the branch was removed, it will not be traversed.
|
||||
// make sure to traverse here.
|
||||
(0, transform_1.traverseNode)(node, context);
|
||||
// call on exit
|
||||
if (onExit)
|
||||
onExit();
|
||||
// make sure to reset currentNode after traversal to indicate this
|
||||
// node has been removed.
|
||||
context.currentNode = null;
|
||||
}
|
||||
else {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.processIf = processIf;
|
||||
function findVIfSpreadElement({ properties }) {
|
||||
const len = properties.length;
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const prop = properties[i];
|
||||
if ((0, types_1.isSpreadElement)(prop)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
function findVIfConditionalExpression(vIfConditionalExpression) {
|
||||
if ((0, types_1.isConditionalExpression)(vIfConditionalExpression.alternate)) {
|
||||
return findVIfConditionalExpression(vIfConditionalExpression.alternate);
|
||||
}
|
||||
return vIfConditionalExpression;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import { type DirectiveTransform } from '@vue/compiler-core';
|
||||
export declare const transformModel: DirectiveTransform;
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformModel = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const compiler_dom_1 = require("@vue/compiler-dom");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const codegen_1 = require("../codegen");
|
||||
const vOn_1 = require("./vOn");
|
||||
const transformModel = (dir, node, _context) => {
|
||||
const context = _context;
|
||||
const baseResult = (0, compiler_core_1.transformModel)(dir, node, _context);
|
||||
// base transform has errors OR component v-model (only need props)
|
||||
if (!baseResult.props.length || node.tagType === compiler_core_1.ElementTypes.COMPONENT) {
|
||||
return transformComponentVModel(baseResult.props, node, context);
|
||||
}
|
||||
if (dir.arg) {
|
||||
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT, dir.arg.loc));
|
||||
}
|
||||
function checkDuplicatedValue() {
|
||||
const value = (0, compiler_core_1.findDir)(node, 'bind');
|
||||
if (value && (0, compiler_core_1.isStaticArgOf)(value.arg, 'value')) {
|
||||
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE, value.loc));
|
||||
}
|
||||
}
|
||||
const { tag } = node;
|
||||
if (tag === 'input' || tag === 'textarea') {
|
||||
checkDuplicatedValue();
|
||||
}
|
||||
else {
|
||||
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT, dir.loc));
|
||||
}
|
||||
if (dir.modifiers.length) {
|
||||
const arg = dir.arg;
|
||||
const modifiers = dir.modifiers
|
||||
.map((m) => ((0, compiler_core_1.isSimpleIdentifier)(m) ? m : JSON.stringify(m)) + `: true`)
|
||||
.join(`, `);
|
||||
const modifiersKey = arg
|
||||
? (0, compiler_core_1.isStaticExp)(arg)
|
||||
? `${arg.content}Modifiers`
|
||||
: (0, compiler_core_1.createCompoundExpression)([arg, ' + "Modifiers"'])
|
||||
: `modelModifiers`;
|
||||
baseResult.props.push((0, compiler_core_1.createObjectProperty)(modifiersKey, (0, compiler_core_1.createSimpleExpression)(`{ ${modifiers} }`, false, dir.loc, compiler_core_1.ConstantTypes.CAN_HOIST)));
|
||||
}
|
||||
return transformElementVModel(baseResult.props, node, context);
|
||||
};
|
||||
exports.transformModel = transformModel;
|
||||
function findInputDirectiveNode(props) {
|
||||
return props.find((prop) => prop.type === compiler_core_1.NodeTypes.DIRECTIVE &&
|
||||
prop.name === 'on' &&
|
||||
prop.arg?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
prop.arg.content === 'input');
|
||||
}
|
||||
function transformElementVModel(props, node, context) {
|
||||
const dirs = transformVModel(props, node, context, {
|
||||
isComponent: false,
|
||||
binding: 'value',
|
||||
event: 'input',
|
||||
formatEventCode(code) {
|
||||
return code.replace(/=\s\$event/g, `= $event.detail.value`);
|
||||
},
|
||||
});
|
||||
if (dirs.length === 2) {
|
||||
// 快手小程序的 input v-model 被转换到 data-e-o 中,补充到 data-e-o 中
|
||||
const inputExp = findDatasetEventOpts(node);
|
||||
if (inputExp) {
|
||||
inputExp.children[2] = combineVOn(dirs[1].exp, inputExp.children[2], node, context);
|
||||
dirs.length = 1;
|
||||
}
|
||||
else {
|
||||
const inputDir = findInputDirectiveNode(node.props);
|
||||
if (inputDir && inputDir.exp) {
|
||||
// 合并到已有的 input 事件中
|
||||
inputDir.exp = combineVOn(dirs[1].exp, inputDir.exp, node, context);
|
||||
dirs.length = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { props: dirs };
|
||||
}
|
||||
/**
|
||||
* {
|
||||
* "type": 7,
|
||||
* "name": "bind",
|
||||
* "loc": {},
|
||||
* "modifiers": [],
|
||||
* "arg": {
|
||||
* "type": 4,
|
||||
* "loc": {},
|
||||
* "content": "data-e-o",
|
||||
* "isStatic": true,
|
||||
* "constType": 3
|
||||
* },
|
||||
* "exp": {
|
||||
* "type": 8,
|
||||
* "loc": {},
|
||||
* "children": ["{", {
|
||||
* "type": 8,
|
||||
* "loc": {},
|
||||
* "children": ["'input'", ": ", {
|
||||
* "type": 8,
|
||||
* "loc": {},
|
||||
* "children": ["_o(", {
|
||||
* "type": 4,
|
||||
* "content": "_ctx.input",
|
||||
* "isStatic": false,
|
||||
* "constType": 0,
|
||||
* "loc": {}
|
||||
* }, ")"]
|
||||
* }, ","]
|
||||
* }, "}"]
|
||||
* }
|
||||
* }
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
function findDatasetEventOpts(node) {
|
||||
const eventOptsProp = (0, compiler_core_1.findProp)(node, uni_cli_shared_1.ATTR_DATASET_EVENT_OPTS, true, false);
|
||||
if (!eventOptsProp) {
|
||||
return;
|
||||
}
|
||||
const { exp } = eventOptsProp;
|
||||
if (exp?.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < exp.children.length; i++) {
|
||||
const childExp = exp.children[i];
|
||||
if ((0, shared_1.isSymbol)(childExp) || (0, shared_1.isString)(childExp)) {
|
||||
continue;
|
||||
}
|
||||
if (childExp.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
continue;
|
||||
}
|
||||
if (childExp.children[0] !== `'input'`) {
|
||||
continue;
|
||||
}
|
||||
const inputExp = childExp.children[2];
|
||||
if ((0, shared_1.isSymbol)(inputExp) ||
|
||||
(0, shared_1.isString)(inputExp) ||
|
||||
inputExp.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
continue;
|
||||
}
|
||||
return childExp;
|
||||
}
|
||||
}
|
||||
function parseVOn(exp, context) {
|
||||
return (0, codegen_1.genExpr)(exp).slice(context.helperString(runtimeHelpers_1.V_ON).length + 1, -1);
|
||||
}
|
||||
function combineVOn(exp1, exp2, node, context) {
|
||||
return (0, vOn_1.wrapperVOn)((0, compiler_core_1.createCompoundExpression)([
|
||||
`[`,
|
||||
parseVOn(exp1, context),
|
||||
',',
|
||||
parseVOn(exp2, context),
|
||||
`]`,
|
||||
]), node, context);
|
||||
}
|
||||
function transformComponentVModel(props, node, context) {
|
||||
return {
|
||||
props: transformVModel(props, node, context, {
|
||||
isComponent: true,
|
||||
formatEventCode(code) {
|
||||
return code;
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
function transformVModel(props, node, context, { isComponent, binding, event, formatEventCode, }) {
|
||||
if (props.length < 2) {
|
||||
return [];
|
||||
}
|
||||
const { key: modelValueArg, value: modelValeExpr } = props[0];
|
||||
const { key: onUpdateArg, value: onUpdateExpr } = props[1];
|
||||
if (modelValueArg.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
return [];
|
||||
}
|
||||
if (onUpdateArg.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
|
||||
!onUpdateArg.content.startsWith('onUpdate:')) {
|
||||
return [];
|
||||
}
|
||||
const vBindModelValue = (0, uni_cli_shared_1.createBindDirectiveNode)(binding || modelValueArg.content, (0, codegen_1.genExpr)(modelValeExpr));
|
||||
const modifiers = parseVModelModifiers(props[2]);
|
||||
// onUpdateExpr 通常是 ExpressionNode 或者被 cache 的 ExpressionNode
|
||||
const vOnValue = (onUpdateExpr.type === compiler_core_1.NodeTypes.JS_CACHE_EXPRESSION
|
||||
? onUpdateExpr.value
|
||||
: onUpdateExpr);
|
||||
const vOnUpdate = (0, uni_cli_shared_1.createOnDirectiveNode)(event || (0, shared_1.camelize)(onUpdateArg.content.replace('onUpdate:', 'update-')), formatEventCode((0, codegen_1.genExpr)((0, vOn_1.wrapperVOn)(modifiers
|
||||
? wrapperVModelModifiers(vOnValue, modifiers, context, isComponent)
|
||||
: vOnValue, node, context))));
|
||||
return [vBindModelValue, vOnUpdate];
|
||||
}
|
||||
function parseVModelModifiers(property) {
|
||||
if (property &&
|
||||
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.key) &&
|
||||
property.key.content.endsWith('Modifiers') &&
|
||||
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.value)) {
|
||||
return property.value.content;
|
||||
}
|
||||
}
|
||||
function wrapperVModelModifiers(exp, modifiers, context, isComponent = false) {
|
||||
return (0, compiler_core_1.createCompoundExpression)([
|
||||
`${context.helperString(runtimeHelpers_1.WITH_MODEL_MODIFIERS)}(`,
|
||||
exp,
|
||||
',',
|
||||
modifiers,
|
||||
`${isComponent ? `, true` : ``}`,
|
||||
`)`,
|
||||
]);
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type DirectiveNode, type DirectiveTransform, type ElementNode, type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export interface VOnDirectiveNode extends DirectiveNode {
|
||||
arg: ExpressionNode;
|
||||
exp: SimpleExpressionNode | undefined;
|
||||
}
|
||||
export declare const transformOn: DirectiveTransform;
|
||||
export declare function wrapperVOn(value: ExpressionNode, node: ElementNode, context: TransformContext): ExpressionNode;
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.wrapperVOn = exports.transformOn = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const __1 = require("..");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
const vFor_1 = require("./vFor");
|
||||
const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;
|
||||
const transformOn = (dir, node, _context, augmentor) => {
|
||||
const context = _context;
|
||||
const { loc, modifiers, arg } = dir;
|
||||
if (!dir.exp && !modifiers.length) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ON_NO_EXPRESSION, loc));
|
||||
}
|
||||
let eventName;
|
||||
if (arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (arg.isStatic) {
|
||||
const rawName = arg.content;
|
||||
// for all event listeners, auto convert it to camelCase. See issue #2249
|
||||
eventName = (0, compiler_core_1.createSimpleExpression)((0, shared_1.toHandlerKey)((0, shared_1.camelize)(rawName)), true, arg.loc);
|
||||
}
|
||||
else {
|
||||
// #2388
|
||||
eventName = (0, compiler_core_1.createCompoundExpression)([
|
||||
// `${context.helperString(TO_HANDLER_KEY)}(`,
|
||||
arg,
|
||||
// `)`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// already a compound expression.
|
||||
eventName = arg;
|
||||
eventName.children.unshift(`${context.helperString(compiler_core_1.TO_HANDLER_KEY)}(`);
|
||||
eventName.children.push(`)`);
|
||||
}
|
||||
// handler processing
|
||||
let exp = dir.exp;
|
||||
if (exp && !exp.content.trim()) {
|
||||
exp = undefined;
|
||||
}
|
||||
let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;
|
||||
if (exp) {
|
||||
const isMemberExp = (0, compiler_core_1.isMemberExpression)(exp.content, context);
|
||||
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));
|
||||
const hasMultipleStatements = exp.content.includes(`;`);
|
||||
// process the expression since it's been skipped
|
||||
if (context.prefixIdentifiers) {
|
||||
isInlineStatement && context.addIdentifiers(`$event`);
|
||||
exp = dir.exp = (0, transformExpression_1.processExpression)(exp, context, false, hasMultipleStatements);
|
||||
isInlineStatement && context.removeIdentifiers(`$event`);
|
||||
// with scope analysis, the function is hoistable if it has no reference
|
||||
// to scope variables.
|
||||
shouldCache =
|
||||
context.cacheHandlers &&
|
||||
// unnecessary to cache inside v-once
|
||||
!context.inVOnce &&
|
||||
// runtime constants don't need to be cached
|
||||
// (this is analyzed by compileScript in SFC <script setup>)
|
||||
!(exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&
|
||||
// #1541 bail if this is a member exp handler passed to a component -
|
||||
// we need to use the original function to preserve arity,
|
||||
// e.g. <transition> relies on checking cb.length to determine
|
||||
// transition end handling. Inline function is ok since its arity
|
||||
// is preserved even when cached.
|
||||
!(isMemberExp && node.tagType === compiler_core_1.ElementTypes.COMPONENT) &&
|
||||
// bail if the function references closure variables (v-for, v-slot)
|
||||
// it must be passed fresh to avoid stale values.
|
||||
!(0, compiler_core_1.hasScopeRef)(exp, context.identifiers) &&
|
||||
// wxs event
|
||||
!isFilterExpr(exp, context);
|
||||
// If the expression is optimizable and is a member expression pointing
|
||||
// to a function, turn it into invocation (and wrap in an arrow function
|
||||
// below) so that it always accesses the latest value when called - thus
|
||||
// avoiding the need to be patched.
|
||||
if (shouldCache && isMemberExp) {
|
||||
if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
exp.content = `${exp.content} && ${exp.content}(...args)`;
|
||||
}
|
||||
else {
|
||||
exp.children = [...exp.children, ` && `, ...exp.children, `(...args)`];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isInlineStatement || (shouldCache && isMemberExp)) {
|
||||
// wrap inline statement in a function expression
|
||||
exp = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${isInlineStatement
|
||||
? context.isTS
|
||||
? `($event: any)`
|
||||
: `$event`
|
||||
: `${context.isTS ? `\n//@ts-ignore\n` : ``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,
|
||||
exp,
|
||||
hasMultipleStatements ? `}` : `)`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
let ret = {
|
||||
props: [
|
||||
(0, compiler_core_1.createObjectProperty)(eventName, exp || (0, compiler_core_1.createSimpleExpression)(`() => {}`, false, loc)),
|
||||
],
|
||||
};
|
||||
// apply extended compiler augmentor
|
||||
if (augmentor) {
|
||||
ret = augmentor(ret);
|
||||
}
|
||||
// TODO
|
||||
if (shouldCache) {
|
||||
// cache handlers so that it's always the same handler being passed down.
|
||||
// this avoids unnecessary re-renders when users use inline handlers on
|
||||
// components.
|
||||
// ret.props[0].value = wrapper(
|
||||
// context.cache(ret.props[0].value) as ExpressionNode,
|
||||
// context
|
||||
// )
|
||||
ret.props[0].value = wrapperVOn(ret.props[0].value, node, context);
|
||||
}
|
||||
else {
|
||||
ret.props[0].value = wrapperVOn(ret.props[0].value, node, context);
|
||||
}
|
||||
// mark the key as handler for props normalization check
|
||||
ret.props.forEach((p) => (p.key.isHandlerKey = true));
|
||||
return ret;
|
||||
};
|
||||
exports.transformOn = transformOn;
|
||||
function isFilterExpr(value, context) {
|
||||
if (context.filters.length && value.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
const firstChild = value.children[0];
|
||||
if (firstChild.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
context.filters.includes(firstChild.content)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function wrapperVOn(value, node, context) {
|
||||
if ((0, transformExpression_1.isBuiltInIdentifier)(value)) {
|
||||
return value;
|
||||
}
|
||||
// wxs event
|
||||
if (isFilterExpr(value, context)) {
|
||||
return value;
|
||||
}
|
||||
const keys = [];
|
||||
if (context.miniProgram.event?.key && context.inVFor) {
|
||||
let keyProp = (0, compiler_core_1.findProp)(node, 'key');
|
||||
if (!keyProp) {
|
||||
const vForScope = (0, vFor_1.parseVForScope)(context.currentScope);
|
||||
if (vForScope) {
|
||||
keyProp = (0, compiler_core_1.findProp)(vForScope.node, 'key');
|
||||
}
|
||||
}
|
||||
// 对 for 中的所有事件增加 key 标记,避免微信小程序不更新事件对象
|
||||
if (keyProp && (0, uni_cli_shared_1.isDirectiveNode)(keyProp) && keyProp.exp) {
|
||||
const keyCode = (0, __1.genExpr)(keyProp.exp);
|
||||
if (keyCode) {
|
||||
keys.push(',');
|
||||
keys.push((0, __1.genExpr)(keyProp.exp));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0, compiler_core_1.createCompoundExpression)([
|
||||
`${context.helperString(runtimeHelpers_1.V_ON)}(`,
|
||||
value,
|
||||
...keys,
|
||||
`)`,
|
||||
]);
|
||||
}
|
||||
exports.wrapperVOn = wrapperVOn;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { type BinaryExpression } from '@babel/types';
|
||||
import { type ComponentNode, type CompoundExpressionNode, type DirectiveNode } from '@vue/compiler-core';
|
||||
import type { CodegenScope, CodegenVForScope } from '../options';
|
||||
import { type NodeTransform, type TransformContext } from '../transform';
|
||||
export declare const transformSlot: NodeTransform;
|
||||
export declare function rewriteVSlot(dir: DirectiveNode, context: TransformContext): void;
|
||||
export declare function findSlotName(slotDir: DirectiveNode): string | CompoundExpressionNode;
|
||||
export declare function findCurrentPath(id: string, scope: CodegenScope): BinaryExpression | import("@babel/types").StringLiteral;
|
||||
/**
|
||||
* 目前无用
|
||||
* @param vForScope
|
||||
* @param parentScope
|
||||
* @param context
|
||||
*/
|
||||
export declare function rewriteScopedSlotVForScope(vForScope: CodegenVForScope, parentScope: CodegenScope, context: TransformContext): void;
|
||||
export declare function createVSlotCallExpression(slotComponent: ComponentNode, vForScope: CodegenVForScope, context: TransformContext): import("@babel/types").CallExpression;
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVSlotCallExpression = exports.rewriteScopedSlotVForScope = exports.findCurrentPath = exports.findSlotName = exports.rewriteVSlot = exports.transformSlot = void 0;
|
||||
const types_1 = require("@babel/types");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const ast_1 = require("../ast");
|
||||
const codegen_1 = require("../codegen");
|
||||
const transform_1 = require("../transform");
|
||||
const utils_1 = require("./utils");
|
||||
const vFor_1 = require("./vFor");
|
||||
const runtimeHelpers_2 = require("../runtimeHelpers");
|
||||
const transformSlot = (node, context) => {
|
||||
if (!(0, uni_cli_shared_1.isUserComponent)(node, context)) {
|
||||
return;
|
||||
}
|
||||
const { tag, children } = node;
|
||||
const slots = new Set();
|
||||
const onComponentSlot = (0, compiler_core_1.findDir)(node, 'slot', true);
|
||||
const implicitDefaultChildren = [];
|
||||
const isMiniProgramComponent = context.isMiniProgramComponent(tag);
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const slotElement = children[i];
|
||||
let slotDir;
|
||||
if (!(0, compiler_core_1.isTemplateNode)(slotElement) ||
|
||||
!(slotDir = (0, compiler_core_1.findDir)(slotElement, 'slot', true))) {
|
||||
// not a <template v-slot>, skip.
|
||||
if (slotElement.type !== compiler_core_1.NodeTypes.COMMENT) {
|
||||
implicitDefaultChildren.push(slotElement);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (onComponentSlot) {
|
||||
// already has on-component slot - this is incorrect usage.
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc));
|
||||
break;
|
||||
}
|
||||
if (!slotDir.arg) {
|
||||
// v-slot => v-slot:default
|
||||
slotDir.arg = (0, compiler_core_1.createSimpleExpression)('default', true);
|
||||
}
|
||||
const slotName = transformTemplateSlotElement(slotDir, slotElement, node, context);
|
||||
// 小程序组件默认插槽,直接移除<template #default>节点
|
||||
if (isMiniProgramComponent) {
|
||||
if (slotName === 'default' && slotElement.children.length === 1) {
|
||||
children.splice(i, 1, slotElement.children[0]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (slotName) {
|
||||
slots.add(slotName);
|
||||
}
|
||||
}
|
||||
if (isMiniProgramComponent) {
|
||||
return;
|
||||
}
|
||||
if (implicitDefaultChildren.length) {
|
||||
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
|
||||
}
|
||||
if (onComponentSlot) {
|
||||
// <unicloud-db v-slot:default="{data, loading, error, options}"/>
|
||||
// => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db>
|
||||
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
|
||||
const templateNode = createTemplateNode(onComponentSlot, implicitDefaultChildren);
|
||||
transformTemplateSlotElement(onComponentSlot, templateNode, node, context);
|
||||
node.children = [templateNode];
|
||||
}
|
||||
// 不支持 $slots, 则自动补充 props
|
||||
if (slots.size && !context.miniProgram.slot.$slots) {
|
||||
const slotsArr = [...slots];
|
||||
const hasDynamic = slotsArr.find((name) => !(0, shared_1.isString)(name));
|
||||
let value;
|
||||
if (hasDynamic) {
|
||||
const children = [];
|
||||
const len = slotsArr.length - 1;
|
||||
slotsArr.forEach((name, index) => {
|
||||
if ((0, shared_1.isString)(name)) {
|
||||
children.push(`'${(0, uni_shared_1.dynamicSlotName)(name)}'`);
|
||||
}
|
||||
else {
|
||||
children.push(name);
|
||||
}
|
||||
if (index < len) {
|
||||
children.push(',');
|
||||
}
|
||||
});
|
||||
value = (0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '([',
|
||||
...children,
|
||||
'])',
|
||||
]);
|
||||
}
|
||||
else {
|
||||
value = `[${slotsArr
|
||||
.map((name) => `'${(0, uni_shared_1.dynamicSlotName)(name)}'`)
|
||||
.join(',')}]`;
|
||||
}
|
||||
node.props.unshift((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_SLOTS, value));
|
||||
}
|
||||
};
|
||||
exports.transformSlot = transformSlot;
|
||||
function rewriteVSlot(dir, context) {
|
||||
dir.arg = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
|
||||
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '(',
|
||||
dir.arg,
|
||||
')',
|
||||
]), context);
|
||||
}
|
||||
exports.rewriteVSlot = rewriteVSlot;
|
||||
function transformTemplateSlotElement(slotDir, slotTemplate, slotComponent, context) {
|
||||
const slotName = findSlotName(slotDir);
|
||||
if (!slotName) {
|
||||
return;
|
||||
}
|
||||
const { exp } = slotDir;
|
||||
// non scoped slots
|
||||
if (!exp) {
|
||||
return slotName;
|
||||
}
|
||||
// empty
|
||||
if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {
|
||||
return slotName;
|
||||
}
|
||||
// 使用vFor来简单处理scoped slot作用域问题
|
||||
slotTemplate.children = [
|
||||
createVForTemplate(slotTemplate, { name: slotName, value: (0, codegen_1.genExpr)(exp), slotComponent }, context),
|
||||
];
|
||||
if (context.miniProgram.slot.dynamicSlotNames) {
|
||||
// 已经在 vFor 中补充 slot,故需要移除 slotTemplate 中的
|
||||
const index = slotTemplate.props.indexOf(slotDir);
|
||||
if (index > -1) {
|
||||
slotTemplate.props.splice(index, 1);
|
||||
}
|
||||
}
|
||||
// v-slot="slotProps" => v-slot 避免 transformIdentifier 生成 slotProps 的变量声明
|
||||
slotDir.exp = undefined;
|
||||
return slotName;
|
||||
}
|
||||
function createTemplateNode(slotDir, children) {
|
||||
return {
|
||||
type: compiler_core_1.NodeTypes.ELEMENT,
|
||||
tag: 'template',
|
||||
tagType: compiler_core_1.ElementTypes.TEMPLATE,
|
||||
loc: compiler_core_1.locStub,
|
||||
isSelfClosing: false,
|
||||
codegenNode: undefined,
|
||||
ns: 0,
|
||||
props: [slotDir],
|
||||
children,
|
||||
};
|
||||
}
|
||||
function findSlotName(slotDir) {
|
||||
if (!slotDir.arg) {
|
||||
return uni_shared_1.SLOT_DEFAULT_NAME;
|
||||
}
|
||||
if ((0, compiler_core_1.isStaticExp)(slotDir.arg)) {
|
||||
return slotDir.arg.content;
|
||||
}
|
||||
return slotDir.arg;
|
||||
}
|
||||
exports.findSlotName = findSlotName;
|
||||
function findCurrentVForValueAlias(context) {
|
||||
let scope = context.currentScope;
|
||||
while (scope) {
|
||||
if ((0, transform_1.isVForScope)(scope)) {
|
||||
return scope.valueAlias;
|
||||
}
|
||||
scope = scope.parent;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function createVForTemplate(slotElement, { name, value, slotComponent, }, context) {
|
||||
const slotName = 's' + context.scopes.vFor;
|
||||
const keyProp = (0, uni_cli_shared_1.createBindDirectiveNode)('key', 'i' + context.scopes.vFor);
|
||||
const source = (0, shared_1.isString)(name) ? `'${name}'` : (0, codegen_1.genExpr)(name);
|
||||
const vForProp = {
|
||||
type: compiler_core_1.NodeTypes.DIRECTIVE,
|
||||
name: 'for',
|
||||
loc: compiler_core_1.locStub,
|
||||
modifiers: [],
|
||||
arg: undefined,
|
||||
exp: (0, compiler_core_1.createSimpleExpression)(`(${value}, ${slotName}) in ${utils_1.SCOPED_SLOT_IDENTIFIER}(${source}, ${findCurrentVForValueAlias(context) || `''`})`),
|
||||
};
|
||||
const props = [vForProp, keyProp];
|
||||
if (context.miniProgram.slot.dynamicSlotNames) {
|
||||
props.push((0, uni_cli_shared_1.createBindDirectiveNode)('slot', slotName));
|
||||
}
|
||||
return {
|
||||
loc: slotElement.loc,
|
||||
ns: 0,
|
||||
tag: 'template',
|
||||
type: compiler_core_1.NodeTypes.ELEMENT,
|
||||
tagType: compiler_core_1.ElementTypes.TEMPLATE,
|
||||
props,
|
||||
isSelfClosing: false,
|
||||
codegenNode: undefined,
|
||||
children: slotElement.children,
|
||||
slotComponent,
|
||||
};
|
||||
}
|
||||
const slotNameRE = /\('(.*)',/;
|
||||
/**
|
||||
* ('default','') => default
|
||||
* @param source
|
||||
* @returns
|
||||
*/
|
||||
function findCurrentSlotName(source) {
|
||||
return (0, types_1.stringLiteral)((0, uni_shared_1.dynamicSlotName)(source.children[1].match(slotNameRE)[1]));
|
||||
}
|
||||
function createPathBinaryExpr(scope, computed = true) {
|
||||
return (0, types_1.binaryExpression)('+', (0, types_1.binaryExpression)('+', (0, types_1.stringLiteral)(parseVForPath(scope.sourceAlias) + (computed ? '[' : '.')), (0, types_1.identifier)(scope.indexAlias)), (0, types_1.stringLiteral)(computed ? '].' : '.'));
|
||||
}
|
||||
function findCurrentPath(id, scope) {
|
||||
let parent = scope.parent;
|
||||
let binaryExpr = null;
|
||||
while (parent) {
|
||||
if ((0, transform_1.isVForScope)(parent)) {
|
||||
// const computed = !isScopedSlotVFor(parent)
|
||||
if (!binaryExpr) {
|
||||
binaryExpr = createPathBinaryExpr(parent);
|
||||
}
|
||||
else {
|
||||
binaryExpr = (0, types_1.binaryExpression)('+', createPathBinaryExpr(parent), binaryExpr);
|
||||
}
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
return ((binaryExpr && (0, types_1.binaryExpression)('+', binaryExpr, (0, types_1.stringLiteral)(id))) ||
|
||||
(0, types_1.stringLiteral)(id));
|
||||
}
|
||||
exports.findCurrentPath = findCurrentPath;
|
||||
function findCurrentVueIdExpr(node, context) {
|
||||
if (!node) {
|
||||
return (0, types_1.stringLiteral)('');
|
||||
}
|
||||
const vueIdProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_ID);
|
||||
if (vueIdProp.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
return (0, types_1.stringLiteral)(vueIdProp.value.content);
|
||||
}
|
||||
return (0, ast_1.parseExpr)((0, codegen_1.genExpr)(vueIdProp.exp), context) || (0, types_1.stringLiteral)('');
|
||||
}
|
||||
/**
|
||||
* 目前无用
|
||||
* @param vForScope
|
||||
* @param parentScope
|
||||
* @param context
|
||||
*/
|
||||
function rewriteScopedSlotVForScope(vForScope, parentScope, context) {
|
||||
// 生成一个新的sourceAlias,用于scopedSlots
|
||||
const { source, sourceExpr } = vForScope;
|
||||
vForScope.sourceAlias = (0, utils_1.rewriteExpressionWithoutProperty)(source, context, sourceExpr, parentScope).content;
|
||||
}
|
||||
exports.rewriteScopedSlotVForScope = rewriteScopedSlotVForScope;
|
||||
function parseVForPath(id) {
|
||||
return id.includes('.') ? id.split('.')[1] : id;
|
||||
}
|
||||
function createVSlotCallExpression(slotComponent, vForScope, context) {
|
||||
const { source, sourceAlias } = vForScope;
|
||||
const id = parseVForPath(sourceAlias);
|
||||
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.WITH_SCOPED_SLOT)), [
|
||||
(0, vFor_1.createVForArrowFunctionExpression)(vForScope),
|
||||
(0, types_1.objectExpression)([
|
||||
// 插槽名称,数据更新 path,vueId
|
||||
(0, types_1.objectProperty)((0, types_1.identifier)('name'), findCurrentSlotName(source)),
|
||||
// 暂不生成 path
|
||||
(0, types_1.objectProperty)((0, types_1.identifier)('path'), findCurrentPath(id, vForScope)),
|
||||
(0, types_1.objectProperty)((0, types_1.identifier)('vueId'), findCurrentVueIdExpr(slotComponent, context)),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
exports.createVSlotCallExpression = createVSlotCallExpression;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformText: NodeTransform;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformText = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const transformText = (node, _) => {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return;
|
||||
}
|
||||
const dir = (0, compiler_core_1.findDir)(node, 'text');
|
||||
if (!dir) {
|
||||
return;
|
||||
}
|
||||
// remove v-text
|
||||
node.props.splice(node.props.indexOf(dir), 1);
|
||||
if (node.tagType !== compiler_core_1.ElementTypes.ELEMENT) {
|
||||
return;
|
||||
}
|
||||
node.isSelfClosing = false;
|
||||
node.children = [
|
||||
{
|
||||
type: compiler_core_1.NodeTypes.INTERPOLATION,
|
||||
loc: dir.exp.loc,
|
||||
content: dir.exp,
|
||||
},
|
||||
];
|
||||
};
|
||||
exports.transformText = transformText;
|
||||
Reference in New Issue
Block a user