初始化fy

This commit is contained in:
yziiy
2025-08-11 11:51:38 +08:00
parent 98ce20e897
commit 7e21160e13
19770 changed files with 3108698 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
import { ParseResult } from '@babel/parser';
import { ObjectProperty, ObjectExpression, Expression, SpreadElement, ConditionalExpression, Identifier, NumericLiteral, StringLiteral, Literal } from '@babel/types';
import { ExpressionNode } from '@vue/compiler-core';
import { CodegenScope, CodegenVIfScope } from './options';
import { TransformContext } from './transform';
export declare function createIdentifier(name: string): Identifier;
export declare function createObjectProperty(name: string, value: Expression): ObjectProperty;
export declare function createSpreadElement(argument: ConditionalExpression): SpreadElement;
export declare function createObjectExpression(properties: Array<ObjectProperty | SpreadElement>): ObjectExpression;
export declare function createVIfProperty(condition: Expression, { id }: CodegenScope): ObjectProperty;
export declare function createVIfConditionalExpression({ condition, properties, }: CodegenVIfScope): ConditionalExpression;
export declare function createVIfSpreadElement(vIfScope: CodegenVIfScope): SpreadElement;
export declare function parseExpr(code: string | ExpressionNode, context: TransformContext, node?: ExpressionNode): ParseResult<Expression> | undefined;
export declare function parseParam(code: string, context: TransformContext, node: ExpressionNode): Identifier | import("@babel/types").RestElement | import("@babel/types").Pattern;
export declare function isUndefined(expr: Expression): boolean;
export declare function isTrueExpr(expr: Literal): boolean;
export declare function parseStringLiteral(expr: Expression | Identifier | StringLiteral | NumericLiteral): StringLiteral;

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseStringLiteral = exports.isTrueExpr = exports.isUndefined = exports.parseParam = exports.parseExpr = exports.createVIfSpreadElement = exports.createVIfConditionalExpression = exports.createVIfProperty = exports.createObjectExpression = exports.createSpreadElement = exports.createObjectProperty = exports.createIdentifier = void 0;
const shared_1 = require("@vue/shared");
const parser_1 = require("@babel/parser");
const types_1 = require("@babel/types");
const compiler_core_1 = require("@vue/compiler-core");
const codegen_1 = require("./codegen");
function createIdentifier(name) {
return (0, types_1.identifier)(name);
}
exports.createIdentifier = createIdentifier;
function createObjectProperty(name, value) {
return (0, types_1.objectProperty)((0, types_1.identifier)(name), value);
}
exports.createObjectProperty = createObjectProperty;
function createSpreadElement(argument) {
return (0, types_1.spreadElement)(argument);
}
exports.createSpreadElement = createSpreadElement;
function createObjectExpression(properties) {
return (0, types_1.objectExpression)(properties);
}
exports.createObjectExpression = createObjectExpression;
function createVIfProperty(condition, { id }) {
return (0, types_1.objectProperty)((0, types_1.identifier)(id.next()), condition);
}
exports.createVIfProperty = createVIfProperty;
function createVIfConditionalExpression({ condition, properties, }) {
return (0, types_1.conditionalExpression)(condition, (0, types_1.objectExpression)(properties), (0, types_1.objectExpression)([]));
}
exports.createVIfConditionalExpression = createVIfConditionalExpression;
function createVIfSpreadElement(vIfScope) {
return (0, types_1.spreadElement)(createVIfConditionalExpression(vIfScope));
}
exports.createVIfSpreadElement = createVIfSpreadElement;
// function numericLiteralToArrayExpr(num: number) {
// const elements: NumericLiteral[] = []
// for (let i = 0; i < num; i++) {
// elements.push(numericLiteral(i + 1))
// }
// return arrayExpression(elements)
// }
function parseExpr(code, context, node) {
if (!(0, shared_1.isString)(code)) {
node = code;
code = (0, codegen_1.genExpr)(code);
}
try {
return (0, parser_1.parseExpression)(code, {
plugins: context.expressionPlugins,
});
}
catch (e) {
context.onError((0, compiler_core_1.createCompilerError)(45 /* ErrorCodes.X_INVALID_EXPRESSION */, node && node.loc, undefined, '\n' + code + '\n' + e.message));
}
}
exports.parseExpr = parseExpr;
function parseParam(code, context, node) {
const { params: [expr], } = parseExpr(`(${code})=>{}`, context, node);
return expr;
}
exports.parseParam = parseParam;
function isUndefined(expr) {
return (0, types_1.isIdentifier)(expr) && expr.name === 'undefined';
}
exports.isUndefined = isUndefined;
function isTrueExpr(expr) {
if ((0, types_1.isNullLiteral)(expr)) {
return false;
}
if ((0, types_1.isStringLiteral)(expr) ||
(0, types_1.isNumericLiteral)(expr) ||
(0, types_1.isBooleanLiteral)(expr) ||
(0, types_1.isBigIntLiteral)(expr) ||
(0, types_1.isDecimalLiteral)(expr)) {
return !!expr.value;
}
return true;
}
exports.isTrueExpr = isTrueExpr;
function parseStringLiteral(expr) {
if ((0, types_1.isIdentifier)(expr)) {
return (0, types_1.stringLiteral)(expr.name);
}
if ((0, types_1.isStringLiteral)(expr)) {
return (0, types_1.stringLiteral)(expr.value);
}
return (0, types_1.stringLiteral)('');
}
exports.parseStringLiteral = parseStringLiteral;

View File

@@ -0,0 +1,14 @@
import { CodegenResult, CompoundExpressionNode, InterpolationNode, SimpleExpressionNode, TextNode } from '@vue/compiler-core';
import { Expression } from '@babel/types';
import { GeneratorOptions } from '@babel/generator';
import { CodegenOptions, CodegenRootNode } from './options';
export declare function generate(ast: CodegenRootNode, options: CodegenOptions): Omit<CodegenResult, 'ast'>;
type CodegenNode = SimpleExpressionNode | CompoundExpressionNode | InterpolationNode | TextNode;
interface GenNodeContext {
code: string;
helper(key: symbol): string;
push(code: string, node?: CodegenNode): void;
}
export declare function genBabelExpr(expr: Expression, opts?: GeneratorOptions): string;
export declare function genExpr(node: CodegenNode | symbol | string, context?: GenNodeContext): string;
export {};

View File

@@ -0,0 +1,325 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.genExpr = exports.genBabelExpr = exports.generate = void 0;
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const generator_1 = __importDefault(require("@babel/generator"));
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
function generate(ast, options) {
const context = createCodegenContext(ast, options);
const { mode, push, indent, deindent, newline, prefixIdentifiers } = context;
const helpers = Array.from(ast.helpers);
const hasHelpers = helpers.length > 0;
const useWithBlock = !prefixIdentifiers && mode !== 'module';
const isSetupInlined = !!options.inline;
// preambles
// in setup() inline mode, the preamble is generated in a sub context
// and returned separately.
const preambleContext = isSetupInlined
? createCodegenContext(ast, options)
: context;
if (mode === 'module') {
genModulePreamble(ast, preambleContext, isSetupInlined);
}
else {
genFunctionPreamble(ast, preambleContext);
}
// enter render function
const functionName = `render`;
const args = ['_ctx', '_cache'];
if (options.bindingMetadata && !options.inline) {
// binding optimization args
args.push('$props', '$setup', '$data', '$options');
}
const signature = options.isTS
? args.map((arg) => `${arg}: any`).join(',')
: args.join(', ');
if (isSetupInlined) {
push(`(${signature}) => {`);
}
else {
push(`function ${functionName}(${signature}) {`);
}
indent();
if (useWithBlock) {
push(`with (_ctx) {`);
indent();
if (hasHelpers) {
push(`const { ${helpers
.map((s) => `${compiler_core_1.helperNameMap[s]}: _${compiler_core_1.helperNameMap[s]}`)
.join(', ')} } = _Vue`);
push(`\n`);
newline();
}
}
push(`return `);
push(genBabelExpr(ast.renderData, options.generatorOpts));
if (useWithBlock) {
deindent();
push(`}`);
}
deindent();
push(`}`);
return {
code: context.code,
preamble: isSetupInlined ? preambleContext.code : ``,
// SourceMapGenerator does have toJSON() method but it's not in the types
map: context.map ? context.map.toJSON() : undefined,
};
}
exports.generate = generate;
function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', filename = `template.vue.html`, scopeId = null, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, isTS = false, sourceMap = false, }) {
const context = {
mode,
prefixIdentifiers,
filename,
scopeId,
runtimeGlobalName,
runtimeModuleName,
bindingComponents: ast.bindingComponents,
isTS,
source: ast.loc.source,
code: ``,
column: 1,
line: 1,
offset: 0,
indentLevel: 0,
push(code, node) {
context.code += code;
if (context.map) {
if (node) {
let name;
if (node.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !node.isStatic) {
const content = node.content.replace(/^_ctx\./, '');
if (content !== node.content && (0, compiler_core_1.isSimpleIdentifier)(content)) {
name = content;
}
}
addMapping(node.loc.start, name);
}
(0, compiler_core_1.advancePositionWithMutation)(context, code);
if (node && node.loc !== compiler_core_1.locStub) {
addMapping(node.loc.end);
}
}
},
indent() {
newline(++context.indentLevel);
},
deindent(withoutNewLine = false) {
if (withoutNewLine) {
--context.indentLevel;
}
else {
newline(--context.indentLevel);
}
},
newline() {
newline(context.indentLevel);
},
};
function newline(n) {
context.push('\n' + ` `.repeat(n));
}
function addMapping(loc, name) {
context.map.addMapping({
name,
source: context.filename || '',
original: {
line: loc.line,
column: loc.column - 1, // source-map column is 0 based
},
generated: {
line: context.line,
column: context.column - 1,
},
});
}
// 暂时无需提供 sourcemap 支持
// if (sourceMap) {
// // lazy require source-map implementation
// context.map = new SourceMapGenerator()
// context.map!.setSourceContent(filename, context.source)
// }
return context;
}
function genComponentImports(bindingComponents, { push, newline }) {
const tags = Object.keys(bindingComponents);
const importDeclarations = [];
// 仅记录easycom和setup组件
const components = [];
tags.forEach((tag) => {
const { name, type } = bindingComponents[tag];
if (type === "unknown" /* BindingComponentTypes.UNKNOWN */) {
const source = (0, uni_cli_shared_1.matchEasycom)(tag);
if (source) {
// 调整为easycom命名
const easycomName = name.replace('component', 'easycom');
bindingComponents[tag].name = easycomName;
components.push(easycomName);
(0, uni_cli_shared_1.addImportDeclaration)(importDeclarations, easycomName, source);
}
}
else if (type === "setup" /* BindingComponentTypes.SETUP */) {
components.push(name);
}
});
if (tags.length) {
push(`const __BINDING_COMPONENTS__ = '` +
JSON.stringify(bindingComponents) +
`'`);
const resolveComponents = [];
const names = [];
Object.keys(bindingComponents).forEach((id) => {
const { type, name } = bindingComponents[id];
if (type === "unknown" /* BindingComponentTypes.UNKNOWN */) {
resolveComponents.push(`const ${name} = _${compiler_core_1.helperNameMap[compiler_core_1.RESOLVE_COMPONENT]}("${id}");`);
names.push(name);
}
});
if (resolveComponents.length) {
newline();
push(`if (!Array) {`);
resolveComponents.forEach((code) => {
push(code);
});
push(`(${names.join('+')})()`);
push(`}`);
}
newline();
importDeclarations.forEach((str) => push(str));
if (importDeclarations.length) {
newline();
}
if (components.length) {
push(`if (!Math) {`);
push(` (${components.map((name) => name).join('+')})() `);
push(`}`);
newline();
}
}
}
function genFunctionPreamble(ast, context) {
const { prefixIdentifiers, push, newline, runtimeGlobalName, bindingComponents, } = context;
const VueBinding = runtimeGlobalName;
const aliasHelper = (s) => `${compiler_core_1.helperNameMap[s]}: _${compiler_core_1.helperNameMap[s]}`;
const helpers = Array.from(ast.helpers);
if (helpers.length > 0) {
if (prefixIdentifiers) {
push(`const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`);
}
else {
push(`const _Vue = ${VueBinding}\n`);
}
}
genComponentImports(bindingComponents, context);
newline();
push(`return `);
}
function genModulePreamble(ast, context, inline) {
const { push, newline, runtimeModuleName, bindingComponents } = context;
const helpers = Array.from(ast.helpers);
if (helpers.length) {
push(`import { ${helpers
.map((s) => `${compiler_core_1.helperNameMap[s]} as _${compiler_core_1.helperNameMap[s]}`)
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`);
}
if (ast.imports.length) {
genImports(ast.imports, context);
}
genComponentImports(bindingComponents, context);
newline();
if (!inline) {
push(`export `);
}
}
function genImports(importsOptions, { push, newline }) {
if (!importsOptions.length) {
return;
}
importsOptions.forEach((imports) => {
push(`import `);
push(genExpr(imports.exp));
push(` from '${imports.path}'`);
newline();
});
}
function createGenNodeContext() {
const context = {
code: '',
helper(key) {
return `_${compiler_core_1.helperNameMap[key]}`;
},
push(code) {
context.code += code;
},
};
return context;
}
function genBabelExpr(expr, opts = {}) {
if (!(0, shared_1.hasOwn)(opts, 'jsescOption')) {
opts.jsescOption = {};
}
opts.jsescOption.quotes = 'single';
return (0, generator_1.default)(expr, opts).code;
}
exports.genBabelExpr = genBabelExpr;
function genExpr(node, context) {
return genNode(node, context).code;
}
exports.genExpr = genExpr;
function genNode(node, context) {
if (!context) {
context = createGenNodeContext();
}
if ((0, shared_1.isString)(node)) {
context.push(node);
return context;
}
if ((0, shared_1.isSymbol)(node)) {
context.push(context.helper(node));
return context;
}
switch (node.type) {
case 2 /* NodeTypes.TEXT */:
genText(node, context);
break;
case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
genExpression(node, context);
break;
case 5 /* NodeTypes.INTERPOLATION */:
genInterpolation(node, context);
break;
case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
genCompoundExpression(node, context);
break;
}
return context;
}
function genText(node, context) {
context.push(JSON.stringify(node.content), node);
}
function genExpression(node, context) {
const { content, isStatic } = node;
context.push(isStatic ? JSON.stringify(content) : content, node);
}
function genInterpolation(node, context) {
const { push, helper } = context;
push(`${helper(compiler_core_1.TO_DISPLAY_STRING)}(`);
genExpr(node.content, context);
push(`)`);
}
function genCompoundExpression(node, context) {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if ((0, shared_1.isString)(child)) {
context.push(child);
}
else {
genExpr(child, context);
}
}
}

View File

@@ -0,0 +1,13 @@
import { CodegenRootNode, CompilerOptions } from './options';
import { DirectiveTransform, NodeTransform } from './transform';
export type TransformPreset = [
NodeTransform[],
Record<string, DirectiveTransform>
];
export declare function getBaseTransformPreset({ prefixIdentifiers, skipTransformIdentifier, }: {
prefixIdentifiers: boolean;
skipTransformIdentifier: boolean;
}): TransformPreset;
export declare function baseCompile(template: string, options?: CompilerOptions): Omit<import("@vue/compiler-core").CodegenResult, "ast"> & {
ast: CodegenRootNode;
};

View File

@@ -0,0 +1,112 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.baseCompile = exports.getBaseTransformPreset = void 0;
const fs_1 = __importDefault(require("fs"));
const compiler_core_1 = require("@vue/compiler-core");
const shared_1 = require("@vue/shared");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const codegen_1 = require("./codegen");
const transform_1 = require("./transform");
const transformExpression_1 = require("./transforms/transformExpression");
const transformIdentifier_1 = require("./transforms/transformIdentifier");
const vIf_1 = require("./transforms/vIf");
const vFor_1 = require("./transforms/vFor");
const codegen_2 = require("./template/codegen");
const vOn_1 = require("./transforms/vOn");
const transformElement_1 = require("./transforms/transformElement");
const vBind_1 = require("./transforms/vBind");
const transformComponent_1 = require("./transforms/transformComponent");
const vSlot_1 = require("./transforms/vSlot");
const transformRoot_1 = require("./transforms/transformRoot");
const transformTag_1 = require("./transforms/transformTag");
const vHtml_1 = require("./transforms/vHtml");
const vText_1 = require("./transforms/vText");
const transformAttr_1 = require("./transforms/transformAttr");
function getBaseTransformPreset({ prefixIdentifiers, skipTransformIdentifier, }) {
// order is important
const nodeTransforms = [
transformRoot_1.transformRoot,
transformAttr_1.transformAttr,
transformTag_1.transformTag,
vHtml_1.transformHtml,
vText_1.transformText,
vIf_1.transformIf,
vFor_1.transformFor,
vSlot_1.transformSlot,
];
if (!skipTransformIdentifier) {
nodeTransforms.push(transformIdentifier_1.transformIdentifier);
}
nodeTransforms.push(transformElement_1.transformElement);
nodeTransforms.push(transformComponent_1.transformComponent);
if (prefixIdentifiers) {
nodeTransforms.push(transformExpression_1.transformExpression);
}
return [
nodeTransforms,
{ on: vOn_1.transformOn, bind: vBind_1.transformBind },
];
}
exports.getBaseTransformPreset = getBaseTransformPreset;
function baseCompile(template, options = {}) {
const prefixIdentifiers = options.prefixIdentifiers === true || options.mode === 'module';
const ast = ((0, shared_1.isString)(template) ? (0, compiler_core_1.baseParse)(template, options) : template);
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset({
prefixIdentifiers,
skipTransformIdentifier: options.skipTransformIdentifier === true,
});
options.hashId = genHashId(options);
if (options.filename) {
if (!options.filters && options.miniProgram?.filter) {
options.filters = parseFilters(options.miniProgram.filter.lang, options.filename);
}
}
const context = (0, transform_1.transform)(ast, (0, shared_1.extend)({}, options, {
prefixIdentifiers,
nodeTransforms: [...nodeTransforms, ...(options.nodeTransforms || [])],
directiveTransforms: (0, shared_1.extend)({}, directiveTransforms, options.directiveTransforms || {}),
}));
const result = (0, shared_1.extend)((0, codegen_1.generate)((0, shared_1.extend)(ast, {
bindingComponents: context.bindingComponents,
}), options), { ast });
if (options.filename && options.miniProgram?.emitFile) {
const { class: clazz, directive, emitFile, event, slot, lazyElement, component, } = options.miniProgram;
(0, codegen_2.generate)(ast, {
class: clazz,
scopeId: options.scopeId,
filename: options.filename,
directive,
emitFile,
event,
slot,
lazyElement,
component,
isBuiltInComponent: context.isBuiltInComponent,
isMiniProgramComponent: context.isMiniProgramComponent,
});
}
return result;
}
exports.baseCompile = baseCompile;
function genHashId(options) {
if (options.hashId) {
return options.hashId;
}
if (options.scopeId) {
return options.scopeId.replace('data-v-', '');
}
if (options.filename) {
return (0, uni_cli_shared_1.hash)(options.filename);
}
return '';
}
function parseFilters(lang, filename) {
filename = filename.split('?')[0];
if (fs_1.default.existsSync(filename)) {
return (0, uni_cli_shared_1.parseFilterNames)(lang, fs_1.default.readFileSync(filename, 'utf8'));
}
return [];
}

View File

@@ -0,0 +1,2 @@
import { ParserOptions } from '@vue/compiler-core';
export declare const decodeHtml: ParserOptions['decodeEntities'];

View File

@@ -0,0 +1,131 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeHtml = void 0;
const namedChars_json_1 = __importDefault(require("./namedChars.json"));
// lazy compute this to make this file tree-shakable for browser
let maxCRNameLength;
const decodeHtml = (rawText, asAttr) => {
let offset = 0;
const end = rawText.length;
let decodedText = '';
function advance(length) {
offset += length;
rawText = rawText.slice(length);
}
while (offset < end) {
const head = /&(?:#x?)?/i.exec(rawText);
if (!head || offset + head.index >= end) {
const remaining = end - offset;
decodedText += rawText.slice(0, remaining);
advance(remaining);
break;
}
// Advance to the "&".
decodedText += rawText.slice(0, head.index);
advance(head.index);
if (head[0] === '&') {
// Named character reference.
let name = '';
let value = undefined;
if (/[0-9a-z]/i.test(rawText[1])) {
if (!maxCRNameLength) {
maxCRNameLength = Object.keys(namedChars_json_1.default).reduce((max, name) => Math.max(max, name.length), 0);
}
for (let length = maxCRNameLength; !value && length > 0; --length) {
name = rawText.slice(1, 1 + length);
value = namedChars_json_1.default[name];
}
if (value) {
const semi = name.endsWith(';');
if (asAttr &&
!semi &&
/[=a-z0-9]/i.test(rawText[name.length + 1] || '')) {
decodedText += '&' + name;
advance(1 + name.length);
}
else {
decodedText += value;
advance(1 + name.length);
}
}
else {
decodedText += '&' + name;
advance(1 + name.length);
}
}
else {
decodedText += '&';
advance(1);
}
}
else {
// Numeric character reference.
const hex = head[0] === '&#x';
const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;
const body = pattern.exec(rawText);
if (!body) {
decodedText += head[0];
advance(head[0].length);
}
else {
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
let cp = Number.parseInt(body[1], hex ? 16 : 10);
if (cp === 0) {
cp = 0xfffd;
}
else if (cp > 0x10ffff) {
cp = 0xfffd;
}
else if (cp >= 0xd800 && cp <= 0xdfff) {
cp = 0xfffd;
}
else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {
// noop
}
else if ((cp >= 0x01 && cp <= 0x08) ||
cp === 0x0b ||
(cp >= 0x0d && cp <= 0x1f) ||
(cp >= 0x7f && cp <= 0x9f)) {
cp = CCR_REPLACEMENTS[cp] || cp;
}
decodedText += String.fromCodePoint(cp);
advance(body[0].length);
}
}
}
return decodedText;
};
exports.decodeHtml = decodeHtml;
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
const CCR_REPLACEMENTS = {
0x80: 0x20ac,
0x82: 0x201a,
0x83: 0x0192,
0x84: 0x201e,
0x85: 0x2026,
0x86: 0x2020,
0x87: 0x2021,
0x88: 0x02c6,
0x89: 0x2030,
0x8a: 0x0160,
0x8b: 0x2039,
0x8c: 0x0152,
0x8e: 0x017d,
0x91: 0x2018,
0x92: 0x2019,
0x93: 0x201c,
0x94: 0x201d,
0x95: 0x2022,
0x96: 0x2013,
0x97: 0x2014,
0x98: 0x02dc,
0x99: 0x2122,
0x9a: 0x0161,
0x9b: 0x203a,
0x9c: 0x0153,
0x9e: 0x017e,
0x9f: 0x0178,
};

View File

@@ -0,0 +1,16 @@
import { CompilerError, SourceLocation } from '@vue/compiler-core';
export declare const enum MPErrorCodes {
X_V_ON_NO_ARGUMENT = 0,
X_V_ON_DYNAMIC_EVENT = 1,
X_V_BIND_NO_ARGUMENT = 2,
X_V_BIND_DYNAMIC_ARGUMENT = 3,
X_V_BIND_MODIFIER_PROP = 4,
X_V_BIND_MODIFIER_ATTR = 5,
X_V_IS_NOT_SUPPORTED = 6,
X_NOT_SUPPORTED = 7,
X_DYNAMIC_COMPONENT_NOT_SUPPORTED = 8
}
export interface MPCompilerError extends CompilerError {
code: MPErrorCodes;
}
export declare function createMPCompilerError(code: MPErrorCodes, loc?: SourceLocation, additionalMessage?: string): MPCompilerError;

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMPCompilerError = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const MPErrorMessages = {
[0 /* MPErrorCodes.X_V_ON_NO_ARGUMENT */]: 'v-on="" is not supported',
[1 /* MPErrorCodes.X_V_ON_DYNAMIC_EVENT */]: 'v-on:[event]="" is not supported.',
[2 /* MPErrorCodes.X_V_BIND_NO_ARGUMENT */]: 'v-bind="" is not supported.',
[3 /* MPErrorCodes.X_V_BIND_DYNAMIC_ARGUMENT */]: 'v-bind:[name]="" is not supported.',
[4 /* MPErrorCodes.X_V_BIND_MODIFIER_PROP */]: 'v-bind .prop is not supported',
[5 /* MPErrorCodes.X_V_BIND_MODIFIER_ATTR */]: 'v-bind .attr is not supported',
[8 /* MPErrorCodes.X_DYNAMIC_COMPONENT_NOT_SUPPORTED */]: '<component is=""/> is not supported',
[7 /* MPErrorCodes.X_NOT_SUPPORTED */]: 'not supported: ',
[6 /* MPErrorCodes.X_V_IS_NOT_SUPPORTED */]: 'v-is not supported',
};
function createMPCompilerError(code, loc, additionalMessage) {
return (0, compiler_core_1.createCompilerError)(code, loc, MPErrorMessages, additionalMessage);
}
exports.createMPCompilerError = createMPCompilerError;

View File

@@ -0,0 +1,7 @@
export default class IdentifierGenerator {
private _chars;
private _nextIds;
next(): string;
_increment(): void;
[Symbol.iterator](): Generator<string, void, unknown>;
}

View File

@@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class IdentifierGenerator {
constructor() {
// u 被框架占用了,不提供 u 开头的变量名
this._chars = 'abcdefghijklmnopqrstvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
this._nextIds = [0];
}
next() {
const r = [];
for (const char of this._nextIds) {
r.unshift(this._chars[char]);
}
this._increment();
const id = r.join('');
if (keywords.includes(id)) {
return this.next();
}
return id;
}
_increment() {
for (let i = 0; i < this._nextIds.length; i++) {
const val = ++this._nextIds[i];
if (val >= this._chars.length) {
this._nextIds[i] = 0;
}
else {
return;
}
}
this._nextIds.push(0);
}
*[Symbol.iterator]() {
while (true) {
yield this.next();
}
}
}
exports.default = IdentifierGenerator;
const keywords = [
'abstract',
'arguments',
'await',
'boolean',
'break',
'byte',
'case',
'catch',
'char',
'class',
'const',
'continue',
'debugger',
'default',
'delete',
'do',
'double',
'else',
'enum',
'eval',
'export',
'extends',
'false',
'final',
'finally',
'float',
'for',
'function',
'goto',
'if',
'implements',
'import',
'in',
'instanceof',
'int',
'interface',
'let',
'long',
'native',
'new',
'null',
'package',
'private',
'protected',
'public',
'return',
'short',
'static',
'super',
'switch',
'synchronized',
'this',
'throw',
'throws',
'transient',
'true',
'try',
'typeof',
'var',
'void',
'volatile',
'while',
'with',
'yield',
];

View File

@@ -0,0 +1,13 @@
import { CodegenResult, ParserOptions, RootNode } from '@vue/compiler-core';
import { CompilerOptions } from './options';
export type { CompilerOptions } from './options';
export { findProp } from '@vue/compiler-core';
export type { DirectiveNode, NodeTransform, DirectiveTransform, TransformContext, SimpleExpressionNode, } from '@vue/compiler-core';
export { genExpr } from './codegen';
export { rewriteExpression } from './transforms/utils';
export { isForElementNode } from './transforms/vFor';
export { transformOn } from './transforms/vOn';
export { transformModel } from './transforms/vModel';
export * from './runtimeHelpers';
export declare function parse(template: string, options?: ParserOptions): RootNode;
export declare function compile(template: string, options?: CompilerOptions): CodegenResult;

View File

@@ -0,0 +1,44 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compile = exports.parse = exports.transformModel = exports.transformOn = exports.isForElementNode = exports.rewriteExpression = exports.genExpr = exports.findProp = void 0;
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const compile_1 = require("./compile");
const parserOptions_1 = require("./parserOptions");
var compiler_core_2 = require("@vue/compiler-core");
Object.defineProperty(exports, "findProp", { enumerable: true, get: function () { return compiler_core_2.findProp; } });
var codegen_1 = require("./codegen");
Object.defineProperty(exports, "genExpr", { enumerable: true, get: function () { return codegen_1.genExpr; } });
var utils_1 = require("./transforms/utils");
Object.defineProperty(exports, "rewriteExpression", { enumerable: true, get: function () { return utils_1.rewriteExpression; } });
var vFor_1 = require("./transforms/vFor");
Object.defineProperty(exports, "isForElementNode", { enumerable: true, get: function () { return vFor_1.isForElementNode; } });
var vOn_1 = require("./transforms/vOn");
Object.defineProperty(exports, "transformOn", { enumerable: true, get: function () { return vOn_1.transformOn; } });
var vModel_1 = require("./transforms/vModel");
Object.defineProperty(exports, "transformModel", { enumerable: true, get: function () { return vModel_1.transformModel; } });
__exportStar(require("./runtimeHelpers"), exports);
function parse(template, options = {}) {
return (0, compiler_core_1.baseParse)(template, (0, shared_1.extend)({}, parserOptions_1.parserOptions, options));
}
exports.parse = parse;
function compile(template, options = {}) {
return (0, compile_1.baseCompile)(template, (0, shared_1.extend)({}, parserOptions_1.parserOptions, options, {
directiveTransforms: (0, shared_1.extend)({}, options.directiveTransforms || {}),
}));
}
exports.compile = compile;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
import { ParserPlugin } from '@babel/parser';
import { GeneratorOptions } from '@babel/generator';
import { CallExpression, Expression, ObjectExpression, ObjectProperty, SpreadElement } from '@babel/types';
import { NodeTransform as VueNodeTransform, DirectiveTransform as VueDirectiveTransform } from '@vue/compiler-core';
import { MiniProgramCompilerOptions } from '@dcloudio/uni-cli-shared';
import { BindingMetadata, CompilerError, RootNode } from '@vue/compiler-core';
import IdentifierGenerator from './identifier';
import { TransformContext } from './transform';
import { VForOptions } from './transforms/vFor';
export interface CodegenRootNode extends RootNode {
renderData: ObjectExpression | CallExpression;
bindingComponents: TransformContext['bindingComponents'];
}
export interface ErrorHandlingOptions {
onWarn?: (warning: CompilerError) => void;
onError?: (error: CompilerError) => void;
}
interface ParserOptions {
/**
* e.g. platform native elements, e.g. `<div>` for browsers
*/
isNativeTag?: (tag: string) => boolean;
/**
* e.g. native elements that can self-close, e.g. `<img>`, `<br>`, `<hr>`
*/
isVoidTag?: (tag: string) => boolean;
/**
* Separate option for end users to extend the native elements list
*/
isCustomElement?: (tag: string) => boolean | void;
}
interface SharedTransformCodegenOptions {
inline?: boolean;
isTS?: boolean;
root?: string;
filename?: string;
bindingMetadata?: BindingMetadata;
prefixIdentifiers?: boolean;
miniProgram?: MiniProgramCompilerOptions;
}
export interface TransformOptions extends SharedTransformCodegenOptions, ErrorHandlingOptions {
hashId?: string | null;
scopeId?: string | null;
filters?: string[];
renderDataSpread?: boolean;
cacheHandlers?: boolean;
nodeTransforms?: VueNodeTransform[];
directiveTransforms?: Record<string, VueDirectiveTransform | undefined>;
isBuiltInComponent?: (tag: string) => symbol | void;
isCustomElement?: (tag: string) => boolean | void;
expressionPlugins?: ParserPlugin[];
skipTransformIdentifier?: boolean;
bindingCssVars?: string[];
}
export interface CodegenRootScope {
id: IdentifierGenerator;
identifiers: string[];
properties: (ObjectProperty | SpreadElement)[];
parent: CodegenScope | null;
}
export interface CodegenVIfScopeInit {
name: 'if' | 'else-if' | 'else' | string;
condition?: Expression;
}
export type CodegenVForScopeInit = VForOptions & {
locals: string[];
};
export interface CodegenVIfScope extends CodegenRootScope, CodegenVIfScopeInit {
parentScope: CodegenRootScope | CodegenVForScope;
}
export interface CodegenVForScope extends CodegenRootScope, CodegenVForScopeInit {
}
export type CodegenScope = CodegenRootScope | CodegenVIfScope | CodegenVForScope;
export interface CodegenOptions extends SharedTransformCodegenOptions {
mode?: 'module' | 'function';
scopeId?: string | null;
sourceMap?: boolean;
runtimeModuleName?: string;
runtimeGlobalName?: string;
generatorOpts?: GeneratorOptions;
}
export interface TemplateCodegenOptions extends Omit<MiniProgramCompilerOptions, 'filter'> {
scopeId?: string | null;
filename: string;
isBuiltInComponent: Required<TransformOptions>['isBuiltInComponent'];
isMiniProgramComponent(name: string): 'plugin' | 'component' | 'dynamicLib' | undefined;
}
export type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions;
export {};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,7 @@
import { ParserOptions } from '@vue/compiler-core';
export declare const enum DOMNamespaces {
HTML = 0,
SVG = 1,
MATH_ML = 2
}
export declare const parserOptions: ParserOptions;

View File

@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parserOptions = void 0;
const shared_1 = require("@vue/shared");
const decodeHtml_1 = require("./decodeHtml");
const isRawTextContainer = /*#__PURE__*/ (0, shared_1.makeMap)('style,iframe,script,noscript', true);
exports.parserOptions = {
isVoidTag: shared_1.isVoidTag,
isNativeTag: (tag) => (0, shared_1.isHTMLTag)(tag) || (0, shared_1.isSVGTag)(tag),
isPreTag: (tag) => tag === 'pre',
decodeEntities: decodeHtml_1.decodeHtml,
// https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher
getNamespace(tag, parent) {
let ns = parent ? parent.ns : 0 /* DOMNamespaces.HTML */;
if (parent && ns === 2 /* DOMNamespaces.MATH_ML */) {
if (parent.tag === 'annotation-xml') {
if (tag === 'svg') {
return 1 /* DOMNamespaces.SVG */;
}
if (parent.props.some((a) => a.type === 6 /* NodeTypes.ATTRIBUTE */ &&
a.name === 'encoding' &&
a.value != null &&
(a.value.content === 'text/html' ||
a.value.content === 'application/xhtml+xml'))) {
ns = 0 /* DOMNamespaces.HTML */;
}
}
else if (/^m(?:[ions]|text)$/.test(parent.tag) &&
tag !== 'mglyph' &&
tag !== 'malignmark') {
ns = 0 /* DOMNamespaces.HTML */;
}
}
else if (parent && ns === 1 /* DOMNamespaces.SVG */) {
if (parent.tag === 'foreignObject' ||
parent.tag === 'desc' ||
parent.tag === 'title') {
ns = 0 /* DOMNamespaces.HTML */;
}
}
if (ns === 0 /* DOMNamespaces.HTML */) {
if (tag === 'svg') {
return 1 /* DOMNamespaces.SVG */;
}
if (tag === 'math') {
return 2 /* DOMNamespaces.MATH_ML */;
}
}
return ns;
},
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments
getTextMode({ tag, ns }) {
if (ns === 0 /* DOMNamespaces.HTML */) {
if (tag === 'textarea' || tag === 'title') {
return 1 /* TextModes.RCDATA */;
}
if (isRawTextContainer(tag)) {
return 2 /* TextModes.RAWTEXT */;
}
}
return 0 /* TextModes.DATA */;
},
};

View File

@@ -0,0 +1,14 @@
export declare const V_ON: unique symbol;
export declare const V_FOR: unique symbol;
export declare const EXTEND: unique symbol;
export declare const SET_REF: unique symbol;
export declare const CAMELIZE: unique symbol;
export declare const HYPHENATE: unique symbol;
export declare const RENDER_PROPS: unique symbol;
export declare const RENDER_SLOT: unique symbol;
export declare const DYNAMIC_SLOT: unique symbol;
export declare const WITH_SCOPED_SLOT: unique symbol;
export declare const STRINGIFY_STYLE: unique symbol;
export declare const NORMALIZE_CLASS: unique symbol;
export declare const TO_DISPLAY_STRING: unique symbol;
export declare const WITH_MODEL_MODIFIERS: unique symbol;

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WITH_MODEL_MODIFIERS = exports.TO_DISPLAY_STRING = exports.NORMALIZE_CLASS = exports.STRINGIFY_STYLE = exports.WITH_SCOPED_SLOT = exports.DYNAMIC_SLOT = exports.RENDER_SLOT = exports.RENDER_PROPS = exports.HYPHENATE = exports.CAMELIZE = exports.SET_REF = exports.EXTEND = exports.V_FOR = exports.V_ON = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
exports.V_ON = Symbol(`vOn`);
exports.V_FOR = Symbol(`vFor`);
exports.EXTEND = Symbol(`extend`);
exports.SET_REF = Symbol(`setRef`);
exports.CAMELIZE = Symbol(`camelize`);
exports.HYPHENATE = Symbol(`hyphenate`);
exports.RENDER_PROPS = Symbol(`renderProps`);
exports.RENDER_SLOT = Symbol(`renderSlot`);
exports.DYNAMIC_SLOT = Symbol(`dynamicSlot`);
exports.WITH_SCOPED_SLOT = Symbol(`withScopedSlot`);
exports.STRINGIFY_STYLE = Symbol(`stringifyStyle`);
exports.NORMALIZE_CLASS = Symbol(`normalizeClass`);
exports.TO_DISPLAY_STRING = Symbol(`toDisplayString`);
exports.WITH_MODEL_MODIFIERS = Symbol(`withModelModifiers`);
(0, compiler_core_1.registerRuntimeHelpers)({
[exports.V_ON]: 'o',
[exports.V_FOR]: 'f',
[exports.EXTEND]: 'e',
[exports.SET_REF]: 'sr',
[exports.CAMELIZE]: 'c',
[exports.HYPHENATE]: 'h',
[exports.RENDER_PROPS]: 'p',
[exports.RENDER_SLOT]: 'r',
[exports.DYNAMIC_SLOT]: 'd',
[exports.WITH_SCOPED_SLOT]: 'w',
[exports.STRINGIFY_STYLE]: 's',
[exports.NORMALIZE_CLASS]: 'n',
[exports.TO_DISPLAY_STRING]: 't',
[exports.WITH_MODEL_MODIFIERS]: 'm',
[uni_cli_shared_1.STRINGIFY_JSON]: 'j',
});

View File

@@ -0,0 +1,19 @@
import { MiniProgramCompilerOptions } from '@dcloudio/uni-cli-shared';
import { ElementNode, RootNode, TemplateChildNode } from '@vue/compiler-core';
import type { TemplateCodegenOptions } from '../options';
import { TransformContext } from '../transform';
export interface TemplateCodegenContext {
code: string;
directive: string;
scopeId?: string | null;
event: MiniProgramCompilerOptions['event'];
slot: MiniProgramCompilerOptions['slot'];
lazyElement: MiniProgramCompilerOptions['lazyElement'];
component: MiniProgramCompilerOptions['component'];
isBuiltInComponent: TransformContext['isBuiltInComponent'];
isMiniProgramComponent: TransformContext['isMiniProgramComponent'];
push(code: string): void;
}
export declare function generate({ children }: RootNode, { slot, event, scopeId, emitFile, filename, directive, lazyElement, isBuiltInComponent, isMiniProgramComponent, component, }: TemplateCodegenOptions): void;
export declare function genNode(node: TemplateChildNode, context: TemplateCodegenContext): void;
export declare function genElementProps(node: ElementNode, virtualHost: boolean, context: TemplateCodegenContext): void;

View File

@@ -0,0 +1,435 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.genElementProps = exports.genNode = exports.generate = void 0;
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 compiler_core_1 = require("@vue/compiler-core");
const codegen_1 = require("../codegen");
const vFor_1 = require("../transforms/vFor");
const vIf_1 = require("../transforms/vIf");
const vSlot_1 = require("../transforms/vSlot");
const utils_1 = require("../transforms/utils");
function generate({ children }, { slot, event, scopeId, emitFile, filename, directive, lazyElement, isBuiltInComponent, isMiniProgramComponent, component, }) {
const context = {
slot,
event,
code: '',
scopeId,
directive,
lazyElement,
component,
isBuiltInComponent,
isMiniProgramComponent,
push(code) {
context.code += code;
},
};
children.forEach((node) => {
genNode(node, context);
});
emitFile({ type: 'asset', fileName: filename, source: context.code });
}
exports.generate = generate;
function genNode(node, context) {
switch (node.type) {
case 9 /* NodeTypes.IF */:
return node.branches.forEach((node) => {
genNode(node, context);
});
case 2 /* NodeTypes.TEXT */:
return genText(node, context);
case 5 /* NodeTypes.INTERPOLATION */:
return genExpression(node.content, context);
case 1 /* NodeTypes.ELEMENT */:
if (node.tagType === 2 /* ElementTypes.SLOT */) {
return genSlot(node, context);
}
else if (node.tagType === 1 /* ElementTypes.COMPONENT */) {
return genComponent(node, context);
}
else if (node.tagType === 3 /* ElementTypes.TEMPLATE */) {
return genTemplate(node, context);
}
else if (isLazyElement(node, context)) {
return genLazyElement(node, context);
}
return genElement(node, context);
}
}
exports.genNode = genNode;
function genText(node, { push }) {
push(node.content);
}
function genExpression(node, { push }) {
push(`{{${(0, codegen_1.genExpr)(node)}}}`);
}
function genVIf(exp, { push, directive }) {
push(` ${directive}if="{{${exp}}}"`);
}
function genVElseIf(exp, { push, directive }) {
push(` ${directive}elif="{{${exp}}}"`);
}
function genVElse({ push, directive }) {
push(` ${directive}else`);
}
function genVFor(node, { push, directive }) {
const { sourceCode, valueAlias, indexAlias } = node.vFor;
push(` ${directive}for="${sourceCode}"`);
if (valueAlias) {
push(` ${directive}for-item="${valueAlias}"`);
}
if (valueAlias === 'index') {
push(` ${directive}for-index="${indexAlias}"`);
}
const keyProp = (0, compiler_core_1.findProp)(node, 'key', true);
if (keyProp) {
const key = keyProp.exp.content;
push(` ${directive}key="${key.includes('.') ? key.split('.')[1] : key}"`);
node.props.splice(node.props.indexOf(keyProp), 1);
}
}
function genSlot(node, context) {
// 移除掉所有非name属性即移除作用域插槽的绑定指令
node.props = node.props.filter((prop) => {
if (prop.type === 6 /* NodeTypes.ATTRIBUTE */) {
return prop.name === 'name';
}
else if (prop.arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
return prop.arg.content === 'name';
}
});
if (!node.children.length || context.slot.fallbackContent) {
// 无后备内容或支持后备内容
return genElement(node, context);
}
const { push } = context;
const isVIfSlot = (0, vIf_1.isIfElementNode)(node);
if (isVIfSlot) {
push(`<block`);
genVIfCode(node, context);
push(`>`);
delete node.vIf;
}
const children = node.children.slice();
node.children.length = 0;
push(`<block`);
const nameProp = (0, compiler_core_1.findProp)(node, 'name');
let name = uni_shared_1.SLOT_DEFAULT_NAME;
if (nameProp) {
if ((0, uni_cli_shared_1.isAttributeNode)(nameProp)) {
if (nameProp.value?.content) {
name = nameProp.value.content;
}
}
else {
if (nameProp.slotName) {
name = nameProp.slotName;
}
}
}
genVIf(`$slots.${name}`, context);
push(`>`);
genElement(node, context);
push(`</block>`);
push(`<block`);
genVElse(context);
push(`>`);
children.forEach((node) => {
genNode(node, context);
});
push(`</block>`);
if (isVIfSlot) {
push(`</block>`);
}
}
function genTemplate(node, context) {
const slotProp = node.props.find((prop) => prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
(prop.name === 'slot' ||
(prop.name === 'bind' &&
prop.arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
prop.arg.content === 'slot')));
// 为 bind 时,通常是作用域插槽生成的 vSlot.ts:197 createBindDirectiveNode('slot',...)
if (slotProp && (slotProp.name === 'bind' || (0, vSlot_1.findSlotName)(slotProp))) {
/**
* 仅百度、字节支持使用 block 作为命名插槽根节点
* 此处为了统一仅默认替换为view
* <template v-slot/> => <view slot="">
*/
node.tag = 'view';
}
else {
// <template/> => <block/>
node.tag = 'block';
}
// @ts-ignore
node.tagType = 0 /* ElementTypes.ELEMENT */;
// 仅单个子节点的命名插槽(非作用域),直接使用子节点作为插槽使用,避免多增加的 view 节点影响 flex 排版
if (slotProp &&
node.tag === 'view' &&
!(0, vFor_1.isForElementNode)(node) &&
node.children.length === 1) {
const child = node.children[0];
if ((0, uni_cli_shared_1.isElementNode)(child) &&
!(0, vFor_1.isForElementNode)(child) &&
!(0, compiler_core_1.isSlotOutlet)(child)) {
child.props.push(slotProp);
return genElement(child, context);
}
}
return genElement(node, context);
}
function genComponent(node, context) {
if (context.component?.getPropertySync) {
return genElement(node, context);
}
if ((0, vIf_1.isIfElementNode)(node) || (0, vFor_1.isForElementNode)(node)) {
return genElement(node, context);
}
// 小程序原生组件,补充 if(r0)
if (context.isMiniProgramComponent(node.tag)) {
;
node.vIf = {
name: 'if',
condition: 'r0',
};
return genElement(node, context);
}
const prop = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_PROPS);
if (!prop) {
return genElement(node, context);
}
;
node.vIf = {
name: 'if',
condition: prop.exp.content,
};
return genElement(node, context);
}
function isLazyElement(node, context) {
if (!context.lazyElement) {
return false;
}
let lazyProps;
if ((0, shared_1.isFunction)(context.lazyElement)) {
const res = context.lazyElement(node, context);
if (!(0, shared_1.isPlainObject)(res)) {
return res;
}
lazyProps = res[node.tag];
}
else {
lazyProps = context.lazyElement[node.tag];
}
if (lazyProps === true) {
return true;
}
if (!lazyProps) {
return;
}
return node.props.some((prop) => prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
lazyProps.find((lazyProp) => {
return (prop.name === lazyProp.name &&
prop.arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
lazyProp.arg.includes(prop.arg.content));
}));
}
/**
* 部分内置组件的部分事件在初始化时会立刻触发但标准事件需要等首次渲染才能确认事件函数故增加wx:if="{{r0}}"
* @param node
* @param context
*/
function genLazyElement(node, context) {
const { push } = context;
if (!(0, vIf_1.isIfElementNode)(node)) {
push(`<block`);
// r0 => ready 首次渲染
genVIf(`r0`, context);
push(`>`);
genElement(node, context);
push(`</block>`);
return;
}
// v-if,v-else-if 无需处理
if (node.vIf.name !== 'else') {
return genElement(node, context);
}
push(`<block`);
genVElse(context);
push(`>`);
node.vIf.name = 'if';
node.vIf.condition = 'r0';
genElement(node, context);
push(`</block>`);
}
function genVIfCode(node, context) {
const { name, condition } = node.vIf;
if (name === 'if') {
genVIf(condition, context);
}
else if (name === 'else-if') {
genVElseIf(condition, context);
}
else if (name === 'else') {
genVElse(context);
}
}
function genElement(node, context) {
const { children, isSelfClosing, props } = node;
let tag = node.tag;
// <template slot="left"/> => <block slot="left"/>
if (tag === 'template') {
if ((0, compiler_core_1.findProp)(node, 'slot')) {
tag = 'view';
}
else {
tag = 'block';
}
}
// 无用的 block
if (tag === 'block' &&
props.length === 0 &&
!(0, vIf_1.isIfElementNode)(node) &&
!(0, vFor_1.isForElementNode)(node)) {
return children.forEach((node) => {
genNode(node, context);
});
}
let virtualHost = false;
if ((0, uni_cli_shared_1.isUserComponent)(node, context)) {
tag = (0, shared_1.hyphenate)(tag);
if (context.component?.normalizeName) {
tag = context.component?.normalizeName(tag);
}
if (context.component?.mergeVirtualHostAttributes) {
virtualHost = true;
}
}
const { push } = context;
const hasVIf = (0, vIf_1.isIfElementNode)(node);
const hasVFor = (0, vFor_1.isForElementNode)(node);
const hasVIfAndVFor = hasVIf && hasVFor;
// 小程序中 wx:else wx:elif 不支持与 wx:for 同时使用
// 故 if 需要补充一层 block
if (hasVIfAndVFor) {
push(`<block`);
genVIfCode(node, context);
push(`>`);
}
push(`<${tag}`);
if (!hasVIfAndVFor && hasVIf) {
genVIfCode(node, context);
}
if (hasVFor) {
genVFor(node, context);
}
if (props.length) {
genElementProps(node, virtualHost, context);
}
if (isSelfClosing) {
push(`/>`);
}
else {
push(`>`);
children.forEach((node) => {
genNode(node, context);
});
push(`</${tag}>`);
}
if (hasVIfAndVFor) {
push(`</block>`);
}
}
function checkVirtualHostProps(name, virtualHost) {
const names = [name];
if (virtualHost) {
const obj = {
style: utils_1.VIRTUAL_HOST_STYLE,
class: utils_1.VIRTUAL_HOST_CLASS,
};
if (name in obj) {
// TODO 支付宝平台移除原有属性(支付宝小程序自定义组件外部属性始终无效)
names.push(obj[name]);
}
return names;
}
return names;
}
function genElementProps(node, virtualHost, context) {
node.props.forEach((prop) => {
if (prop.type === 6 /* NodeTypes.ATTRIBUTE */) {
const { value } = prop;
if (value) {
checkVirtualHostProps(prop.name, virtualHost).forEach((name) => {
context.push(` ${name}="${value.content}"`);
});
}
else {
context.push(` ${prop.name}`);
}
}
else {
const { name } = prop;
if (name === 'on') {
genOn(prop, node, context);
}
else {
genDirectiveNode(prop, node, virtualHost, context);
}
}
});
}
exports.genElementProps = genElementProps;
function genOn(prop, node, { push, event, isBuiltInComponent }) {
const arg = prop.arg.content;
const exp = prop.exp;
const modifiers = prop.modifiers;
const name = (event?.format || uni_cli_shared_1.formatMiniProgramEvent)(arg, {
isCatch: modifiers.includes('stop') || modifiers.includes('prevent'),
isCapture: modifiers.includes('capture'),
isComponent: (0, uni_cli_shared_1.isUserComponent)(node, { isBuiltInComponent }),
});
if (exp.isStatic) {
push(` ${name}="${exp.content}"`);
}
else {
push(` ${name}="{{${exp.content}}}"`);
}
}
function genDirectiveNode(prop, node, virtualHost, context) {
const { push, component } = context;
if (prop.name === 'slot') {
if (prop.arg) {
const arg = prop.arg;
if (arg.isStatic) {
const slotName = (0, uni_shared_1.dynamicSlotName)(arg.content);
// 非作用域默认插槽不生成 slot 属性
if (slotName !== uni_shared_1.SLOT_DEFAULT_NAME) {
push(` slot="${slotName}"`);
}
}
else {
push(` slot="{{${arg.content}}}"`);
}
}
}
else if (prop.name === 'show') {
let hiddenPropName = 'hidden';
if ((0, uni_cli_shared_1.isUserComponent)(node, context) && component && component.vShow) {
hiddenPropName = component.vShow;
}
push(` ${hiddenPropName}="{{!${prop.exp.content}}}"`);
}
else if (prop.arg && prop.exp) {
const arg = prop.arg.content;
const exp = prop.exp.content;
checkVirtualHostProps(arg, virtualHost).forEach((arg) => {
push(` ${arg}="{{${exp}}}"`);
});
}
else {
if (prop.name !== 'bind') {
throw new Error(`unknown directive ` + JSON.stringify(prop));
}
}
}

View File

@@ -0,0 +1,74 @@
import { DirectiveNode, ElementNode, Property, RootNode, ParentNode, TemplateChildNode, CompilerError, ExpressionNode, JSChildNode, CacheExpression } from '@vue/compiler-core';
import { CodegenRootNode, CodegenRootScope, CodegenScope, CodegenVForScope, CodegenVForScopeInit, CodegenVIfScope, CodegenVIfScopeInit, TransformOptions } from './options';
export interface ImportItem {
exp: string | ExpressionNode;
path: string;
}
export type NodeTransform = (node: RootNode | TemplateChildNode, context: TransformContext) => void | (() => void) | (() => void)[];
export type DirectiveTransform = (dir: DirectiveNode, node: ElementNode, context: TransformContext, augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult) => DirectiveTransformResult;
interface DirectiveTransformResult {
props: Property[];
needRuntime?: boolean | symbol;
}
export interface ErrorHandlingOptions {
onWarn?: (warning: CompilerError) => void;
onError?: (error: CompilerError) => void;
}
export declare const enum BindingComponentTypes {
SELF = "self",
SETUP = "setup",
UNKNOWN = "unknown"
}
export interface TransformContext extends Required<Omit<TransformOptions, 'filename' | 'root'>> {
selfName: string | null;
currentNode: RootNode | TemplateChildNode | null;
parent: ParentNode | null;
childIndex: number;
helpers: Map<symbol, number>;
components: Set<string>;
imports: ImportItem[];
bindingComponents: Record<string, {
type: BindingComponentTypes;
name: string;
}>;
identifiers: {
[name: string]: number | undefined;
};
cached: number;
scopes: {
vFor: number;
vueId: number;
};
scope: CodegenRootScope;
currentScope: CodegenScope;
currentVueId: string;
vueIds: string[];
inVOnce: boolean;
inVFor: boolean;
helper<T extends symbol>(name: T): T;
removeHelper<T extends symbol>(name: T): void;
helperString(name: symbol): string;
replaceNode(node: TemplateChildNode): void;
removeNode(node?: TemplateChildNode): void;
onNodeRemoved(): void;
addIdentifiers(exp: ExpressionNode | string): void;
removeIdentifiers(exp: ExpressionNode | string): void;
popScope(): CodegenScope | undefined;
getScopeIndex(scope: CodegenScope): number;
addVIfScope(initScope: CodegenVIfScopeInit): CodegenVIfScope;
addVForScope(initScope: CodegenVForScopeInit): CodegenVForScope;
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T;
isMiniProgramComponent(name: string): 'plugin' | 'component' | 'dynamicLib' | undefined;
rootNode: TemplateChildNode | null;
}
export declare function isRootScope(scope: CodegenScope): scope is CodegenRootScope;
export declare function isVIfScope(scope: CodegenScope): scope is CodegenVIfScope;
export declare function isVForScope(scope: CodegenScope): scope is CodegenVForScope;
export declare function isScopedSlotVFor({ source }: CodegenVForScope): boolean;
export declare function transform(root: CodegenRootNode, options: TransformOptions): TransformContext;
export declare function traverseNode(node: RootNode | TemplateChildNode, context: TransformContext): void;
export declare function traverseChildren(parent: ParentNode, context: TransformContext): void;
export declare function createTransformContext(rootNode: RootNode, { root, filename, isTS, inline, hashId, scopeId, filters, bindingCssVars, bindingMetadata, cacheHandlers, prefixIdentifiers, skipTransformIdentifier, renderDataSpread, nodeTransforms, directiveTransforms, miniProgram, isBuiltInComponent, isCustomElement, expressionPlugins, onError, onWarn, }: TransformOptions): TransformContext;
export declare type StructuralDirectiveTransform = (node: ElementNode, dir: DirectiveNode, context: TransformContext) => void | (() => void);
export declare function createStructuralDirectiveTransform(name: string | RegExp, fn: StructuralDirectiveTransform): NodeTransform;
export {};

View File

@@ -0,0 +1,525 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createStructuralDirectiveTransform = exports.createTransformContext = exports.traverseChildren = exports.traverseNode = exports.transform = exports.isScopedSlotVFor = exports.isVForScope = exports.isVIfScope = exports.isRootScope = void 0;
const shared_1 = require("@vue/shared");
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 identifier_1 = __importDefault(require("./identifier"));
const runtimeHelpers_1 = require("./runtimeHelpers");
const ast_1 = require("./ast");
const utils_1 = require("./transforms/utils");
const codegen_1 = require("./codegen");
function isRootScope(scope) {
return !isVIfScope(scope) && !isVForScope(scope);
}
exports.isRootScope = isRootScope;
function isVIfScope(scope) {
return (!!scope.condition ||
scope.name === 'else');
}
exports.isVIfScope = isVIfScope;
function isVForScope(scope) {
return !!scope.source;
}
exports.isVForScope = isVForScope;
function isScopedSlotVFor({ source }) {
if (source.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
return false;
}
const first = source.children[0];
return (first.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
first.content.includes(utils_1.SCOPED_SLOT_IDENTIFIER));
}
exports.isScopedSlotVFor = isScopedSlotVFor;
function transform(root, options) {
const context = createTransformContext(root, options);
findRootNode(root, context);
traverseNode(root, context);
root.renderData = createRenderDataExpr(context.scope.properties, context);
// finalize meta information
root.helpers = new Set([...context.helpers.keys()]);
root.components = [...context.components];
root.imports = context.imports;
root.cached = context.cached;
return context;
}
exports.transform = transform;
function findRootNode(root, context) {
const children = root.children.filter((node) => node.type === 1 /* NodeTypes.ELEMENT */ && node.tag !== 'template');
if (children.length === 1) {
context.rootNode = children[0];
}
}
function traverseNode(node, context) {
context.currentNode = node;
// apply transform plugins
const { nodeTransforms } = context;
const exitFns = [];
for (let i = 0; i < nodeTransforms.length; i++) {
const onExit = nodeTransforms[i](node, context);
if (onExit) {
if ((0, shared_1.isArray)(onExit)) {
exitFns.push(...onExit);
}
else {
exitFns.push(onExit);
}
}
if (!context.currentNode) {
// node was removed
return;
}
else {
// node may have been replaced
node = context.currentNode;
}
}
switch (node.type) {
case 3 /* NodeTypes.COMMENT */:
// context.helper(CREATE_COMMENT)
break;
case 5 /* NodeTypes.INTERPOLATION */:
context.helper(compiler_core_1.TO_DISPLAY_STRING);
break;
// for container types, further traverse downwards
case 9 /* NodeTypes.IF */:
for (let i = 0; i < node.branches.length; i++) {
traverseNode(node.branches[i], context);
}
break;
case 10 /* NodeTypes.IF_BRANCH */:
case 11 /* NodeTypes.FOR */:
case 1 /* NodeTypes.ELEMENT */:
case 0 /* NodeTypes.ROOT */:
traverseChildren(node, context);
break;
}
// exit transforms
context.currentNode = node;
let i = exitFns.length;
while (i--) {
exitFns[i]();
}
}
exports.traverseNode = traverseNode;
function traverseChildren(parent, context) {
let i = 0;
const nodeRemoved = () => {
i--;
};
for (; i < parent.children.length; i++) {
const child = parent.children[i];
if ((0, shared_1.isString)(child))
continue;
context.parent = parent;
context.childIndex = i;
context.onNodeRemoved = nodeRemoved;
traverseNode(child, context);
}
}
exports.traverseChildren = traverseChildren;
function defaultOnError(error) {
throw error;
}
function defaultOnWarn(msg) {
console.warn(`[Vue warn] ${msg.message}`);
}
function createTransformContext(rootNode, { root = '', filename = '', isTS = false, inline = false, hashId = null, scopeId = null, filters = [], bindingCssVars = [], bindingMetadata = shared_1.EMPTY_OBJ, cacheHandlers = false, prefixIdentifiers = false, skipTransformIdentifier = false, renderDataSpread = false, nodeTransforms = [], directiveTransforms = {}, miniProgram = {
class: {
array: true,
},
slot: {
fallbackContent: false,
dynamicSlotNames: true,
},
directive: '',
}, isBuiltInComponent = shared_1.NOOP, isCustomElement = shared_1.NOOP, expressionPlugins = [], onError = defaultOnError, onWarn = defaultOnWarn, }) {
const rootScope = {
id: new identifier_1.default(),
identifiers: [],
properties: [],
parent: null,
};
function findVIfParentScope() {
for (let i = scopes.length - 1; i >= 0; i--) {
const scope = scopes[i];
if (isVForScope(scope) || isRootScope(scope)) {
return scope;
}
}
return rootScope;
}
function createScope(id, initScope) {
return (0, shared_1.extend)({
id,
properties: [],
parent: scopes[scopes.length - 1],
get identifiers() {
return Object.keys(identifiers);
},
}, initScope);
}
const vueIds = [];
const identifiers = Object.create(null);
const scopes = [rootScope];
const miniProgramComponents = (0, uni_cli_shared_1.findMiniProgramUsingComponents)({
filename,
componentsDir: miniProgram.component?.dir,
inputDir: root,
});
// const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
const context = {
// options
// 暂不提供根据文件名生成递归组件
selfName: '',
miniProgram,
isTS,
inline,
hashId,
scopeId,
filters,
bindingCssVars,
bindingMetadata,
cacheHandlers,
prefixIdentifiers,
nodeTransforms,
directiveTransforms,
expressionPlugins,
skipTransformIdentifier,
renderDataSpread,
isBuiltInComponent,
isCustomElement,
onError,
onWarn,
// state
parent: null,
childIndex: 0,
helpers: new Map(),
components: new Set(),
imports: [],
bindingComponents: Object.create(null),
cached: 0,
identifiers,
scope: rootScope,
scopes: {
vFor: 0,
vueId: 0,
},
get currentScope() {
return scopes[scopes.length - 1];
},
currentNode: rootNode,
vueIds,
get currentVueId() {
return vueIds[vueIds.length - 1];
},
inVOnce: false,
get inVFor() {
let parent = scopes[scopes.length - 1];
while (parent) {
if (isVForScope(parent) && !isScopedSlotVFor(parent)) {
return true;
}
parent = parent.parent;
}
return false;
},
// methods
getScopeIndex(scope) {
return scopes.indexOf(scope);
},
popScope() {
return scopes.pop();
},
addVIfScope(initScope) {
const vIfScope = createScope(scopes[scopes.length - 1].id, (0, shared_1.extend)(initScope, { parentScope: findVIfParentScope() }));
scopes.push(vIfScope);
return vIfScope;
},
addVForScope(initScope) {
const vForScope = createScope(new identifier_1.default(), initScope);
scopes.push(vForScope);
return vForScope;
},
helper(name) {
const count = context.helpers.get(name) || 0;
context.helpers.set(name, count + 1);
return name;
},
removeHelper(name) {
const count = context.helpers.get(name);
if (count) {
const currentCount = count - 1;
if (!currentCount) {
context.helpers.delete(name);
}
else {
context.helpers.set(name, currentCount);
}
}
},
helperString(name) {
return `_${compiler_core_1.helperNameMap[context.helper(name)]}`;
},
replaceNode(node) {
context.parent.children[context.childIndex] = context.currentNode = node;
},
removeNode(node) {
if (!context.parent) {
throw new Error(`Cannot remove root node.`);
}
const list = context.parent.children;
const removalIndex = node
? list.indexOf(node)
: context.currentNode
? context.childIndex
: -1;
/* istanbul ignore if */
if (removalIndex < 0) {
throw new Error(`node being removed is not a child of current parent`);
}
if (!node || node === context.currentNode) {
// current node removed
context.currentNode = null;
context.onNodeRemoved();
}
else {
// sibling node removed
if (context.childIndex > removalIndex) {
context.childIndex--;
context.onNodeRemoved();
}
}
context.parent.children.splice(removalIndex, 1);
},
onNodeRemoved: () => { },
addIdentifiers(exp) {
if ((0, shared_1.isString)(exp)) {
addId(exp);
}
else if (exp.identifiers) {
exp.identifiers.forEach(addId);
}
else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
addId(exp.content);
}
},
removeIdentifiers(exp) {
if ((0, shared_1.isString)(exp)) {
removeId(exp);
}
else if (exp.identifiers) {
exp.identifiers.forEach(removeId);
}
else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
removeId(exp.content);
}
},
cache(exp, isVNode = false) {
return createCacheExpression(context.cached++, exp, isVNode);
},
isMiniProgramComponent(name) {
return miniProgramComponents[name];
},
rootNode: null,
};
function addId(id) {
const { identifiers } = context;
if (identifiers[id] === undefined) {
identifiers[id] = 0;
}
identifiers[id]++;
}
function removeId(id) {
context.identifiers[id]--;
}
return context;
}
exports.createTransformContext = createTransformContext;
function createCacheExpression(index, value, isVNode = false) {
return {
type: 20 /* NodeTypes.JS_CACHE_EXPRESSION */,
index,
value,
isVNode,
loc: compiler_core_1.locStub,
};
}
function createStructuralDirectiveTransform(name, fn) {
const matches = (0, shared_1.isString)(name)
? (n) => n === name
: (n) => name.test(n);
return (node, context) => {
if (node.type === 1 /* NodeTypes.ELEMENT */) {
const { props } = node;
// structural directive transforms are not concerned with slots
// as they are handled separately in vSlot.ts
// if (node.tagType === ElementTypes.TEMPLATE && props.some(isVSlot)) {
// return
// }
const exitFns = [];
for (let i = 0; i < props.length; i++) {
const prop = props[i];
if (prop.type === 7 /* NodeTypes.DIRECTIVE */ && matches(prop.name)) {
// structural directives are removed to avoid infinite recursion
// also we remove them *before* applying so that it can further
// traverse itself in case it moves the node around
props.splice(i, 1);
i--;
const onExit = fn(node, prop, context);
if (onExit)
exitFns.push(onExit);
}
}
return exitFns;
}
};
}
exports.createStructuralDirectiveTransform = createStructuralDirectiveTransform;
function createRenderDataExpr(properties, context) {
const objExpr = (0, ast_1.createObjectExpression)(properties);
if (!hasSpreadElement(objExpr)) {
return objExpr;
}
// filters: ['test']
// v-if="text.aa()"
if (context.filters.length) {
transformFilterObjectSpreadExpr(objExpr, context);
}
if (context.renderDataSpread) {
return objExpr;
}
return transformObjectSpreadExpr(objExpr, context);
}
function hasSpreadElement(expr) {
return expr.properties.some((prop) => {
if ((0, types_1.isSpreadElement)(prop)) {
return true;
}
else {
const returnStatement = parseReturnStatement(prop);
if (returnStatement) {
return hasSpreadElement(returnStatement.argument);
}
}
});
}
// 目前硬编码识别 _f,应该读取 context.helperString
const returnObjExprMap = {
_f: 1,
_w: 0, // _w(()=>{return {}})
};
function parseReturnStatement(prop) {
if ((0, types_1.isObjectProperty)(prop) &&
(0, types_1.isCallExpression)(prop.value) &&
(0, types_1.isIdentifier)(prop.value.callee)) {
const { name } = prop.value.callee;
if ((0, shared_1.hasOwn)(returnObjExprMap, name)) {
return prop.value.arguments[returnObjExprMap[name]].body.body[0];
}
}
}
function transformObjectPropertyExpr(prop, context) {
// vFor,withScopedSlot
const returnStatement = parseReturnStatement(prop);
if (returnStatement) {
const objExpr = returnStatement.argument;
if (hasSpreadElement(objExpr)) {
returnStatement.argument = transformObjectSpreadExpr(objExpr, context);
}
}
return prop;
}
function transformObjectSpreadExpr(objExpr, context) {
const properties = objExpr.properties;
const args = [];
let objExprProperties = [];
properties.forEach((prop) => {
if ((0, types_1.isObjectProperty)(prop)) {
objExprProperties.push(transformObjectPropertyExpr(prop, context));
}
else {
if (objExprProperties.length) {
args.push((0, types_1.objectExpression)(objExprProperties));
}
args.push(transformConditionalExpression(prop.argument, context));
objExprProperties = [];
}
});
if (objExprProperties.length) {
args.push((0, types_1.objectExpression)(objExprProperties));
}
if (args.length === 1) {
return args[0];
}
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.EXTEND)), args);
}
function transformConditionalExpression(expr, context) {
const { consequent, alternate } = expr;
if ((0, types_1.isObjectExpression)(consequent) && hasSpreadElement(consequent)) {
expr.consequent = transformObjectSpreadExpr(consequent, context);
}
if ((0, types_1.isObjectExpression)(alternate)) {
if (hasSpreadElement(alternate)) {
expr.alternate = transformObjectSpreadExpr(alternate, context);
}
}
else if ((0, types_1.isConditionalExpression)(alternate)) {
transformConditionalExpression(alternate, context);
}
return expr;
}
function transformFilterObjectSpreadExpr(objExpr, context) {
const properties = objExpr.properties;
properties.forEach((prop) => {
if ((0, types_1.isObjectProperty)(prop)) {
transformFilterObjectPropertyExpr(prop, context);
}
else {
prop.argument = transformFilterConditionalExpression(prop.argument, context);
}
});
}
function transformFilterObjectPropertyExpr(prop, context) {
// vFor, withScopedSlot
const returnStatement = parseReturnStatement(prop);
if (returnStatement) {
const objExpr = returnStatement.argument;
if (hasSpreadElement(objExpr)) {
transformFilterObjectSpreadExpr(objExpr, context);
}
}
}
function transformFilterConditionalExpression(expr, context) {
const { test, consequent, alternate } = expr;
if ((0, types_1.isObjectExpression)(consequent) && hasSpreadElement(consequent)) {
transformFilterObjectSpreadExpr(consequent, context);
}
if ((0, types_1.isObjectExpression)(alternate)) {
if (hasSpreadElement(alternate)) {
transformFilterObjectSpreadExpr(alternate, context);
}
}
else if ((0, types_1.isConditionalExpression)(alternate)) {
expr.alternate = transformFilterConditionalExpression(alternate, context);
}
const testCode = (0, codegen_1.genBabelExpr)(test);
// filter test
if (context.filters.find((filter) => testCode.includes(filter + '.'))) {
// test.aa() ? {a:1} : {b:2} => {...{a:1},...{b:2}}
const properties = [];
if (!(0, types_1.isObjectExpression)(consequent) || consequent.properties.length) {
properties.push((0, types_1.spreadElement)(consequent));
}
if (!(0, types_1.isObjectExpression)(expr.alternate) ||
expr.alternate.properties.length) {
properties.push((0, types_1.spreadElement)(expr.alternate));
}
return (0, types_1.objectExpression)(properties);
}
return expr;
}

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformAttr: NodeTransform;

View File

@@ -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;

View File

@@ -0,0 +1,6 @@
import { DirectiveNode, AttributeNode } from '@vue/compiler-core';
import { 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;

View File

@@ -0,0 +1,181 @@
"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_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 === 4 /* 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)(utils_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);
}

View File

@@ -0,0 +1,11 @@
import { ComponentNode, DirectiveNode, ElementNode } from '@vue/compiler-core';
import { NodeTransform, 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;

View File

@@ -0,0 +1,208 @@
"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;
}
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 === 6 /* 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,
'eO',
'e-o',
'onVI',
'ref',
'slot',
'key',
'is',
];
function isComponentProp(name) {
if (builtInProps.includes(name)) {
return false;
}
if (name.startsWith('data-')) {
return false;
}
return true;
}
/**
* 重写组件 props 绑定
* @param node
* @param context
*/
function rewriteBinding({ tag, props }, context) {
const isMiniProgramComponent = context.isMiniProgramComponent(tag);
if (isMiniProgramComponent === 'plugin' ||
isMiniProgramComponent === 'dynamicLib') {
// 因无法介入插件类型组件内部实现,故保留原始属性
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 === 4 /* 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' ? `||''` : ''));
}
exports.rewritePropsBinding = rewritePropsBinding;

View File

@@ -0,0 +1,9 @@
import { ElementNode, TemplateLiteral, Property } from '@vue/compiler-core';
import { NodeTransform, 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;

View File

@@ -0,0 +1,199 @@
"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 === 1 /* NodeTypes.ELEMENT */ &&
(node.tagType === 0 /* ElementTypes.ELEMENT */ ||
node.tagType === 1 /* ElementTypes.COMPONENT */))) {
return;
}
if (node.tagType === 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("setup-const" /* BindingTypes.SETUP_CONST */) ||
checkType("setup-reactive-const" /* BindingTypes.SETUP_REACTIVE_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("setup-let" /* BindingTypes.SETUP_LET */) ||
checkType("setup-ref" /* BindingTypes.SETUP_REF */) ||
checkType("setup-maybe-ref" /* 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 === 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 === 7 /* 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)(40 /* 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 === 4 /* 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 === 7 /* NodeTypes.DIRECTIVE */ && prop.name === 'model') {
dirs.push(...transformVModel(prop, node, context)
.props);
props.splice(i, 1);
i--;
}
}
if (dirs.length) {
props.push(...dirs);
}
}

View File

@@ -0,0 +1,5 @@
import { ExpressionNode, SimpleExpressionNode } from '@vue/compiler-core';
import { 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;

View File

@@ -0,0 +1,295 @@
"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 === 5 /* NodeTypes.INTERPOLATION */) {
node.content = processExpression(node.content, context);
}
else if (node.type === 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 === 7 /* 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 === 4 /* 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 === 4 /* 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 (type === "setup-const" /* BindingTypes.SETUP_CONST */ ||
type === "setup-reactive-const" /* BindingTypes.SETUP_REACTIVE_CONST */ ||
localVars[raw]) {
return raw;
}
else if (type === "setup-ref" /* BindingTypes.SETUP_REF */) {
return `${raw}.value`;
}
else if (type === "setup-maybe-ref" /* 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 === "setup-let" /* 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 === "props" /* 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 === "props-aliased" /* 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')) {
// setup bindings in non-inline mode
return `$setup.${raw}`;
}
else if (type === "props-aliased" /* 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 (bindingMetadata[node.content] === "setup-const" /* BindingTypes.SETUP_CONST */) {
node.constType = 1 /* ConstantTypes.CAN_SKIP_PATCH */;
}
node.content = rewriteIdentifier(rawExp);
}
else if (!isScopeVarReference) {
if (isLiteral) {
node.constType = 3 /* ConstantTypes.CAN_STRINGIFY */;
}
else {
node.constType = 2 /* 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)(45 /* 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 ? 3 /* ConstantTypes.CAN_STRINGIFY */ : 0 /* 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
? 0 /* ConstantTypes.NOT_CONSTANT */
: 3 /* 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 === 4 /* 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 !== 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
return false;
}
id = id.content;
}
return builtInIdentifiers.includes(id);
}
exports.isBuiltInIdentifier = isBuiltInIdentifier;

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformIdentifier: NodeTransform;

View File

@@ -0,0 +1,120 @@
"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 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 transformIdentifier = (node, context) => {
return function transformIdentifier() {
if (node.type === 5 /* NodeTypes.INTERPOLATION */) {
const content = node.content;
let isFilter = false;
if (content.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
const firstChild = content.children[0];
isFilter =
!(0, shared_1.isString)(firstChild) &&
!(0, shared_1.isSymbol)(firstChild) &&
firstChild.type === 4 /* 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 === 1 /* NodeTypes.ELEMENT */) {
let hasClassBinding = false;
let hasStyleBinding = false;
(0, transformRef_1.rewriteRef)(node, context);
if ((0, uni_cli_shared_1.isUserComponent)(node, context)) {
(0, transformComponent_1.rewriteBinding)(node, context);
}
const { props } = node;
const virtualHost = !!(context.miniProgram.component?.mergeVirtualHostAttributes &&
context.rootNode === node);
for (let i = 0; i < props.length; i++) {
const dir = props[i];
if (dir.type === 7 /* NodeTypes.DIRECTIVE */) {
const arg = dir.arg;
if (arg) {
// TODO 指令暂不不支持动态参数,v-bind:[arg] v-on:[event]
if (!(arg.type === 4 /* 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);
}
else if ((0, transformComponent_1.isPropsBinding)(dir)) {
(0, transformComponent_1.rewritePropsBinding)(dir, node, 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 (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);
}
}
}
};
};
exports.transformIdentifier = transformIdentifier;
const builtInProps = [utils_1.ATTR_VUE_SLOTS];
function isBuiltIn({ arg, exp }) {
return (arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
builtInProps.includes(arg.content) &&
exp?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */);
}

View File

@@ -0,0 +1,4 @@
import { DirectiveNode } from '@vue/compiler-core';
import { ForElementNode } from './vFor';
export declare function isSelfKey({ arg, exp }: DirectiveNode, vFor: ForElementNode['vFor'] | false): boolean | undefined;
export declare function rewriteSelfKey(dir: DirectiveNode): void;

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteSelfKey = exports.isSelfKey = void 0;
function isSelfKey({ arg, exp }, vFor) {
return (vFor &&
arg &&
exp &&
arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
arg.content === 'key' &&
exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
exp.content === vFor.valueAlias);
}
exports.isSelfKey = isSelfKey;
function rewriteSelfKey(dir) {
;
dir.exp.content = '*this';
}
exports.rewriteSelfKey = rewriteSelfKey;

View File

@@ -0,0 +1,3 @@
import { ElementNode } from '@vue/compiler-core';
import { TransformContext } from '../transform';
export declare function rewriteRef(node: ElementNode, context: TransformContext): void;

View File

@@ -0,0 +1,125 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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(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 };
}
function rewriteRefProp(prop, vueIdProp, context) {
let id = '';
if ((0, uni_cli_shared_1.isDirectiveNode)(vueIdProp)) {
const vueIdExpr = (0, ast_1.parseExpr)(vueIdProp.exp, context, vueIdProp.exp);
if (vueIdExpr) {
id = (0, codegen_1.genBabelExpr)(vueIdExpr);
}
}
else {
id = `'${vueIdProp.value.content}'`;
}
if (!id) {
return;
}
const { code, refKey } = parseRefCode(prop, context);
const opts = Object.create(null);
if (refKey) {
opts.k = refKey;
}
if (context.inVFor) {
opts.f = 1;
}
(0, utils_1.parseExprWithRewrite)(context.helperString(runtimeHelpers_1.SET_REF) +
'(' +
code +
', ' +
id +
(Object.keys(opts).length ? ', ' + JSON.stringify(opts) : '') +
')', prop.loc, context);
}
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));
}

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformRoot: NodeTransform;

View File

@@ -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 !== 0 /* NodeTypes.ROOT */) {
return;
}
if (context.bindingCssVars.length) {
node.children.forEach((child) => {
if (child.type !== 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 === 4 /* 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);
}
}
}

View File

@@ -0,0 +1,6 @@
import { DirectiveNode, SlotOutletNode } from '@vue/compiler-core';
import { TransformContext } from '../transform';
export declare function rewriteSlot(node: SlotOutletNode, context: TransformContext): void;
export interface NameScopedSlotDirectiveNode extends DirectiveNode {
slotName: string;
}

View File

@@ -0,0 +1,187 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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 === 6 /* 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)(36 /* 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 === 6 /* 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;
}
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 === 4 /* 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)}`;
}
}

View File

@@ -0,0 +1,6 @@
import { DirectiveNode, AttributeNode } from '@vue/compiler-core';
import { 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): void;
export declare function createVirtualHostStyle(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;

View File

@@ -0,0 +1,179 @@
"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_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 === 4 /* 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) {
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 {
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)(utils_1.VIRTUAL_HOST_STYLE))
: (0, types_1.identifier)(utils_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;
}

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformTag: NodeTransform;

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformTag = void 0;
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const transformTag = (node, _) => {
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
return;
}
const newTag = uni_cli_shared_1.HTML_TO_MINI_PROGRAM_TAGS[node.tag];
if (newTag) {
node.tag = newTag;
node.tagType = 0 /* ElementTypes.ELEMENT */;
}
};
exports.transformTag = transformTag;

View File

@@ -0,0 +1,27 @@
import { Expression, Identifier, MemberExpression, SpreadElement } from '@babel/types';
import { ElementNode, ExpressionNode, SimpleExpressionNode, SourceLocation, TransformContext as VueTransformContext } from '@vue/compiler-core';
import { CodegenScope } from '../options';
import { 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 SCOPED_SLOT_IDENTIFIER = "__SCOPED_SLOT__";
export declare const VIRTUAL_HOST_STYLE = "virtualHostStyle";
export declare const VIRTUAL_HOST_CLASS = "virtualHostClass";
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: object | null | undefined): boolean;
export declare function removeAttribute(node: ElementNode, name: string): void;

View File

@@ -0,0 +1,137 @@
"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.VIRTUAL_HOST_CLASS = exports.VIRTUAL_HOST_STYLE = exports.SCOPED_SLOT_IDENTIFIER = 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.SCOPED_SLOT_IDENTIFIER = '__SCOPED_SLOT__';
exports.VIRTUAL_HOST_STYLE = 'virtualHostStyle';
exports.VIRTUAL_HOST_CLASS = 'virtualHostClass';
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 === 4 /* 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;

View File

@@ -0,0 +1,2 @@
import { DirectiveTransform } from '../transform';
export declare const transformBind: DirectiveTransform;

View File

@@ -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 !== 4 /* 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 === 4 /* 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.onWarn((0, errors_1.createMPCompilerError)(4 /* MPErrorCodes.X_V_BIND_MODIFIER_PROP */, loc));
}
if (modifiers.includes('attr')) {
context.onWarn((0, errors_1.createMPCompilerError)(5 /* MPErrorCodes.X_V_BIND_MODIFIER_ATTR */, loc));
}
if (!exp ||
(exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !exp.content.trim())) {
context.onError((0, compiler_core_1.createCompilerError)(34 /* 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;

View File

@@ -0,0 +1,37 @@
import { ExpressionNode, SimpleExpressionNode, ElementTypes, ElementNode } from '@vue/compiler-core';
import { NodeTransform, TransformContext } from '../transform';
import { Expression, Identifier, Pattern, RestElement } from '@babel/types';
import { 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;

View File

@@ -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)(31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */, dir.loc));
return;
}
const parseResult = parseForExpression(dir.exp, context);
if (!parseResult) {
context.onError((0, compiler_core_1.createCompilerError)(32 /* 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 === 1 /* NodeTypes.ELEMENT */ && !isForElementNode(c)) {
const key = (0, compiler_core_1.findProp)(c, 'key');
if (key) {
context.onError((0, compiler_core_1.createCompilerError)(33 /* 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 === 4 /* 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: 0 /* 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, compiler_core_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;

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformHtml: NodeTransform;

View File

@@ -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 !== 0 /* ElementTypes.ELEMENT */) {
return;
}
node.isSelfClosing = false;
node.children = [createRichText(node, dir)];
};
exports.transformHtml = transformHtml;
function createRichText(node, dir) {
return {
tag: 'rich-text',
type: 1 /* NodeTypes.ELEMENT */,
tagType: 0 /* ElementTypes.ELEMENT */,
props: [(0, uni_cli_shared_1.createBindDirectiveNode)('nodes', dir.exp || '')],
isSelfClosing: true,
children: [],
codegenNode: undefined,
ns: node.ns,
loc: node.loc,
};
}

View File

@@ -0,0 +1,13 @@
import { DirectiveNode, ElementNode, IfNode } from '@vue/compiler-core';
import { NodeTransform, 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 {};

View File

@@ -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)(30 /* 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)(28 /* 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: 9 /* 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 === 3 /* NodeTypes.COMMENT */) {
context.removeNode(sibling);
continue;
}
if (sibling &&
sibling.type === 2 /* NodeTypes.TEXT */ &&
!sibling.content.trim().length) {
context.removeNode(sibling);
continue;
}
if (sibling && sibling.type === 9 /* 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)(30 /* 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)(30 /* 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;
}

View File

@@ -0,0 +1,2 @@
import { DirectiveTransform } from '@vue/compiler-core';
export declare const transformModel: DirectiveTransform;

View File

@@ -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 === 1 /* ElementTypes.COMPONENT */) {
return transformComponentVModel(baseResult.props, node, context);
}
if (dir.arg) {
context.onError((0, compiler_dom_1.createDOMCompilerError)(56 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));
}
function checkDuplicatedValue() {
const value = (0, compiler_core_1.findProp)(node, 'value');
if (value) {
context.onError((0, compiler_dom_1.createDOMCompilerError)(58 /* 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)(55 /* 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, 2 /* ConstantTypes.CAN_HOIST */)));
}
return transformElementVModel(baseResult.props, node, context);
};
exports.transformModel = transformModel;
function findInputDirectiveNode(props) {
return props.find((prop) => prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
prop.name === 'on' &&
prop.arg?.type === 4 /* 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 !== 8 /* 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 !== 8 /* 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 !== 8 /* 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 !== 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
return [];
}
if (onUpdateArg.type !== 4 /* 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 === 20 /* 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` : ``}`,
`)`,
]);
}

View File

@@ -0,0 +1,8 @@
import { DirectiveNode, ExpressionNode, SimpleExpressionNode, DirectiveTransform, ElementNode } from '@vue/compiler-core';
import { 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;

View File

@@ -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)(35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */, loc));
}
let eventName;
if (arg.type === 4 /* 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 === 4 /* 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 === 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 === 4 /* 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 === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
const firstChild = value.children[0];
if (firstChild.type === 4 /* 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;

View File

@@ -0,0 +1,16 @@
import { BinaryExpression } from '@babel/types';
import { ComponentNode, CompoundExpressionNode, DirectiveNode } from '@vue/compiler-core';
import { CodegenScope, CodegenVForScope } from '../options';
import { NodeTransform, 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;

View File

@@ -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 !== 3 /* NodeTypes.COMMENT */) {
implicitDefaultChildren.push(slotElement);
}
continue;
}
if (onComponentSlot) {
// already has on-component slot - this is incorrect usage.
context.onError((0, compiler_core_1.createCompilerError)(37 /* 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 === 4 /* 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: 1 /* NodeTypes.ELEMENT */,
tag: 'template',
tagType: 3 /* 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: 7 /* 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: 1 /* NodeTypes.ELEMENT */,
tagType: 3 /* 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 === 6 /* 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)([
// 插槽名称,数据更新 pathvueId
(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;

View File

@@ -0,0 +1,2 @@
import { NodeTransform } from '../transform';
export declare const transformText: NodeTransform;

View File

@@ -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 !== 0 /* ElementTypes.ELEMENT */) {
return;
}
node.isSelfClosing = false;
node.children = [
{
type: 5 /* NodeTypes.INTERPOLATION */,
loc: dir.exp.loc,
content: dir.exp,
},
];
};
exports.transformText = transformText;