2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+17
View File
@@ -0,0 +1,17 @@
import { type ParseResult } from '@babel/parser';
import { type ConditionalExpression, type Expression, type Identifier, type Literal, type NumericLiteral, type ObjectExpression, type ObjectProperty, type SpreadElement, type StringLiteral } from '@babel/types';
import { type ExpressionNode } from '@vue/compiler-core';
import type { CodegenScope, CodegenVIfScope } from './options';
import type { 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;
+91
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)(compiler_core_1.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;
+14
View File
@@ -0,0 +1,14 @@
import { type CodegenResult, type CompoundExpressionNode, type InterpolationNode, type SimpleExpressionNode, type TextNode } from '@vue/compiler-core';
import type { Expression } from '@babel/types';
import { type GeneratorOptions } from '@babel/generator';
import type { 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 {};
+333
View File
@@ -0,0 +1,333 @@
"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();
}
}
if (isSetupInlined && options.isX) {
push(`const __returned__ = `);
push(genBabelExpr(ast.renderData, options.generatorOpts));
newline();
push(`return __returned__`);
}
else {
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 === compiler_core_1.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 compiler_core_1.NodeTypes.TEXT:
genText(node, context);
break;
case compiler_core_1.NodeTypes.SIMPLE_EXPRESSION:
genExpression(node, context);
break;
case compiler_core_1.NodeTypes.INTERPOLATION:
genInterpolation(node, context);
break;
case compiler_core_1.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);
}
}
}
+13
View File
@@ -0,0 +1,13 @@
import type { CodegenRootNode, CompilerOptions } from './options';
import { type DirectiveTransform, type 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;
};
+121
View File
@@ -0,0 +1,121 @@
"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");
const utils_1 = require("./transforms/utils");
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, parseMode: 'html' })
: 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);
if (options.isX) {
options.filters.push(utils_1.FILTER_MODULE_NAME);
}
}
}
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, checkPropName, } = 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,
checkPropName,
autoImportFilters: context.autoImportFilters,
filter: options.miniProgram?.filter,
});
}
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 [];
}
+2
View File
@@ -0,0 +1,2 @@
import type { ParserOptions } from '@vue/compiler-core';
export declare const decodeHtml: ParserOptions['decodeEntities'];
+131
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,
};
+16
View File
@@ -0,0 +1,16 @@
import { type CompilerError, type 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;
+19
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;
+7
View File
@@ -0,0 +1,7 @@
export default class IdentifierGenerator {
private _chars;
private _nextIds;
next(): string;
_increment(): void;
[Symbol.iterator](): Generator<string, void, unknown>;
}
+105
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',
];
+13
View File
@@ -0,0 +1,13 @@
import { type CodegenResult, type ParserOptions, type RootNode } from '@vue/compiler-core';
import type { 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;
+44
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
+92
View File
@@ -0,0 +1,92 @@
import type { ParserPlugin } from '@babel/parser';
import type { GeneratorOptions } from '@babel/generator';
import type { CallExpression, Expression, ObjectExpression, ObjectProperty, SpreadElement } from '@babel/types';
import type { DirectiveTransform as VueDirectiveTransform, NodeTransform as VueNodeTransform } from '@vue/compiler-core';
import type { MiniProgramCompilerOptions, MiniProgramComponentsType, MiniProgramFilterOptions } from '@dcloudio/uni-cli-shared';
import type { BindingMetadata, CompilerError, RootNode } from '@vue/compiler-core';
import type IdentifierGenerator from './identifier';
import type { TransformContext } from './transform';
import type { 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;
isX?: 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 MiniProgramCompilerOptions {
scopeId?: string | null;
filename: string;
autoImportFilters: Array<Omit<MiniProgramFilterOptions, 'code'>>;
isBuiltInComponent: Required<TransformOptions>['isBuiltInComponent'];
isMiniProgramComponent(name: string): MiniProgramComponentsType | undefined;
checkPropName?: MiniProgramCompilerOptions['checkPropName'];
}
export type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions;
export {};
+2
View File
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
+7
View File
@@ -0,0 +1,7 @@
import { type ParserOptions } from '@vue/compiler-core';
export declare const enum DOMNamespaces {
HTML = 0,
SVG = 1,
MATH_ML = 2
}
export declare const parserOptions: ParserOptions;
+50
View File
@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parserOptions = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const shared_1 = require("@vue/shared");
exports.parserOptions = {
isVoidTag: shared_1.isVoidTag,
isNativeTag: (tag) => (0, shared_1.isHTMLTag)(tag) || (0, shared_1.isSVGTag)(tag),
isPreTag: (tag) => tag === 'pre',
// 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 === compiler_core_1.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;
},
parseMode: 'html',
};
+16
View File
@@ -0,0 +1,16 @@
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;
export declare const SET_UNI_ELEMENT_ID: unique symbol;
export declare const SET_UNI_ELEMENT_STYLE: unique symbol;
+40
View File
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SET_UNI_ELEMENT_STYLE = exports.SET_UNI_ELEMENT_ID = 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`);
exports.SET_UNI_ELEMENT_ID = Symbol(`setUniElementId`);
exports.SET_UNI_ELEMENT_STYLE = Symbol(`setUniElementStyle`);
(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',
[exports.SET_UNI_ELEMENT_ID]: 'sei',
[exports.SET_UNI_ELEMENT_STYLE]: 'ses',
});
+20
View File
@@ -0,0 +1,20 @@
import { type MiniProgramCompilerOptions } from '@dcloudio/uni-cli-shared';
import { type ElementNode, type RootNode, type TemplateChildNode } from '@vue/compiler-core';
import type { TemplateCodegenOptions } from '../options';
import type { 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;
checkPropName: TemplateCodegenOptions['checkPropName'];
}
export declare function generate({ children }: RootNode, { slot, event, scopeId, emitFile, filename, directive, lazyElement, isBuiltInComponent, isMiniProgramComponent, checkPropName, component, autoImportFilters, filter, }: TemplateCodegenOptions): void;
export declare function genNode(node: TemplateChildNode, context: TemplateCodegenContext): void;
export declare function genElementProps(node: ElementNode, virtualHost: boolean, context: TemplateCodegenContext): void;
+466
View File
@@ -0,0 +1,466 @@
"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, checkPropName, component, autoImportFilters, filter, }) {
const context = {
slot,
event,
code: '',
scopeId,
directive,
lazyElement,
component,
isBuiltInComponent,
isMiniProgramComponent,
checkPropName,
push(code) {
context.code += code;
},
};
children.forEach((node) => {
genNode(node, context);
});
if (filter && filter.generate && autoImportFilters.length) {
autoImportFilters.forEach((autoImportFilter) => {
context.code +=
filter.generate(autoImportFilter, '/common/' + autoImportFilter.id) + '\n';
});
}
emitFile({ type: 'asset', fileName: filename, source: context.code });
}
exports.generate = generate;
function genNode(node, context) {
switch (node.type) {
case compiler_core_1.NodeTypes.IF:
return node.branches.forEach((node) => {
genNode(node, context);
});
case compiler_core_1.NodeTypes.TEXT:
return genText(node, context);
case compiler_core_1.NodeTypes.INTERPOLATION:
return genExpression(node.content, context);
case compiler_core_1.NodeTypes.ELEMENT:
if (node.tagType === compiler_core_1.ElementTypes.SLOT) {
return genSlot(node, context);
}
else if (node.tagType === compiler_core_1.ElementTypes.COMPONENT) {
return genComponent(node, context);
}
else if (node.tagType === compiler_core_1.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 === compiler_core_1.NodeTypes.ATTRIBUTE) {
return prop.name === 'name';
}
else if (prop.arg?.type === compiler_core_1.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;
}
}
}
if (name.includes('-')) {
genVIf(`$slots['${name}']`, context);
}
else {
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 === compiler_core_1.NodeTypes.DIRECTIVE &&
(prop.name === 'slot' ||
(prop.name === 'bind' &&
prop.arg?.type === compiler_core_1.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-expect-error
node.tagType = compiler_core_1.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);
if ((0, vIf_1.isIfElementNode)(node)) {
;
child.vIf = node.vIf;
}
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 === compiler_core_1.NodeTypes.DIRECTIVE &&
lazyProps.find((lazyProp) => {
return (prop.name === lazyProp.name &&
prop.arg?.type === compiler_core_1.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 === compiler_core_1.NodeTypes.ATTRIBUTE) {
if (context.checkPropName &&
!context.checkPropName(prop.name, prop, node)) {
return;
}
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 (context.checkPropName &&
!context.checkPropName(prop.name, prop, node)) {
return;
}
if (name === 'on') {
genOn(prop, node, context);
}
else {
genDirectiveNode(prop, node, virtualHost, context);
}
}
});
}
exports.genElementProps = genElementProps;
function genOn(prop, node, { push, event, isBuiltInComponent }) {
if (!prop.arg) {
return;
}
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;
if (arg === utils_1.ATTR_ELEMENT_ID) {
// 模板忽略生成 u-e,只需要 render 中生成
return;
}
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));
}
}
}
+77
View File
@@ -0,0 +1,77 @@
import { type CacheExpression, type CompilerError, type DirectiveNode, type ElementNode, type ExpressionNode, type JSChildNode, type ParentNode, type Property, type RootNode, type TemplateChildNode } from '@vue/compiler-core';
import type { MiniProgramComponentsType, MiniProgramFilterOptions } from '@dcloudio/uni-cli-shared';
import type { 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[];
autoImportFilters: Array<Omit<MiniProgramFilterOptions, 'code'>>;
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): MiniProgramComponentsType | undefined;
rootNode: TemplateChildNode | null;
elementRefIndex: number;
}
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, { isX, 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 {};
+528
View File
@@ -0,0 +1,528 @@
"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 !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
return false;
}
const first = source.children[0];
return (first.type === compiler_core_1.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 === compiler_core_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 compiler_core_1.NodeTypes.COMMENT:
// context.helper(CREATE_COMMENT)
break;
case compiler_core_1.NodeTypes.INTERPOLATION:
context.helper(compiler_core_1.TO_DISPLAY_STRING);
break;
// for container types, further traverse downwards
case compiler_core_1.NodeTypes.IF:
for (let i = 0; i < node.branches.length; i++) {
traverseNode(node.branches[i], context);
}
break;
case compiler_core_1.NodeTypes.IF_BRANCH:
case compiler_core_1.NodeTypes.FOR:
case compiler_core_1.NodeTypes.ELEMENT:
case compiler_core_1.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, { isX = false, 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
// 暂不提供根据文件名生成递归组件
isX,
selfName: '', //nameMatch && capitalize(camelize(nameMatch[1])),
miniProgram,
isTS,
inline,
hashId,
scopeId,
filters,
autoImportFilters: [],
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 === compiler_core_1.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 === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
removeId(exp.content);
}
},
cache(exp, isVNode = false) {
return createCacheExpression(context.cached++, exp, isVNode);
},
isMiniProgramComponent(name) {
return miniProgramComponents[name];
},
rootNode: null,
elementRefIndex: 0,
};
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: compiler_core_1.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 === compiler_core_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 === compiler_core_1.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, // _f(_ctx.items,()=>{return {}})
_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;
}
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformAttr: NodeTransform;
@@ -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;
@@ -0,0 +1,6 @@
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
import type { TransformContext } from '../transform';
export declare function isClassBinding({ arg }: DirectiveNode): boolean | undefined;
export declare function findStaticClassIndex(props: (AttributeNode | DirectiveNode)[]): number;
export declare function rewriteClass(index: number, classBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext): void;
export declare function createVirtualHostClass(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;
@@ -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 === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'class');
}
exports.isClassBinding = isClassBinding;
function findStaticClassIndex(props) {
return props.findIndex((prop) => prop.name === 'class');
}
exports.findStaticClassIndex = findStaticClassIndex;
function rewriteClass(index, classBindingProp, props, virtualHost, context) {
const expr = classBindingProp.exp
? (0, ast_1.parseExpr)(classBindingProp.exp, context)
: undefined;
let classBindingExpr;
if (expr) {
classBindingExpr = expr;
if ((0, types_1.isObjectExpression)(expr)) {
classBindingExpr = createClassBindingByObjectExpression(rewriteClassObjectExpression(expr, classBindingProp.loc, context));
}
else if ((0, types_1.isArrayExpression)(expr)) {
classBindingExpr = createClassBindingByArrayExpression(rewriteClassArrayExpression(expr, context));
}
else {
classBindingExpr = (0, ast_1.parseExpr)(rewriteClassExpression(classBindingProp.exp, context).content, context);
}
}
else if (virtualHost) {
classBindingExpr = (0, types_1.arrayExpression)([]);
}
else {
return;
}
const staticClassPropIndex = findStaticClassIndex(props);
if (staticClassPropIndex > -1) {
const staticClass = props[staticClassPropIndex].value
.content;
if (staticClass) {
if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
}
const staticClassLiterals = parseStaticClass(staticClass);
if (index > staticClassPropIndex) {
classBindingExpr.elements.unshift(...staticClassLiterals);
}
else {
classBindingExpr.elements.push(...staticClassLiterals);
}
}
}
if (virtualHost) {
if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
}
classBindingExpr.elements.push((0, types_1.identifier)(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);
}
@@ -0,0 +1,11 @@
import { type ComponentNode, type DirectiveNode, type ElementNode } from '@vue/compiler-core';
import { type NodeTransform, type TransformContext } from '../transform';
export declare const transformComponent: NodeTransform;
/**
* 重写组件 props 绑定
* @param node
* @param context
*/
export declare function rewriteBinding({ tag, props }: ComponentNode, context: TransformContext): void;
export declare function isPropsBinding({ arg }: DirectiveNode): boolean | undefined;
export declare function rewritePropsBinding(dir: DirectiveNode, node: ElementNode, context: TransformContext): void;
@@ -0,0 +1,223 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewritePropsBinding = exports.isPropsBinding = exports.rewriteBinding = exports.transformComponent = void 0;
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const transform_1 = require("../transform");
const utils_1 = require("./utils");
const codegen_1 = require("../codegen");
const types_1 = require("@babel/types");
const runtimeHelpers_1 = require("../runtimeHelpers");
const ast_1 = require("../ast");
const vIf_1 = require("./vIf");
const transformComponent = (node, context) => {
if (!(0, uni_cli_shared_1.isUserComponent)(node, context)) {
return;
}
// 新版本的 vue,识别 template 有差异,可能认为是自定义组件
if (node.tag === 'template') {
return;
}
addComponentType(node, context);
addVueId(node, context);
processBooleanAttr(node);
return function postTransformComponent() {
context.vueIds.pop();
};
};
exports.transformComponent = transformComponent;
function addComponentType(node, context) {
if (!context.isMiniProgramComponent(node.tag)) {
return;
}
node.props.push((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_COM_TYPE, 'm'));
}
function addVueId(node, context) {
let { hashId, scopes, currentScope, currentVueId } = context;
if (!hashId) {
return;
}
let vueId = hashId + '-' + scopes.vueId++;
const indexs = [];
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope)) {
indexs.push(`+'-'+${currentScope.indexAlias}`);
}
currentScope = currentScope.parent;
}
const inFor = !!indexs.length;
if (inFor) {
vueId = `'${vueId}'` + indexs.reverse().join('');
}
context.vueIds.push(vueId);
let value = vueId;
if (currentVueId) {
const isParentDynamic = currentVueId.includes('+');
const isCurrentDynamic = vueId.includes('+');
if (isParentDynamic || isCurrentDynamic) {
value = `(${vueId})+','+(${isParentDynamic ? currentVueId : `'${currentVueId}'`})`;
}
else {
value = vueId + ',' + currentVueId;
}
}
if (value.includes('+')) {
return node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_ID, value));
}
return node.props.push((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_VUE_ID, value));
}
/**
* <uni-collapse accordion/> => <uni-collapse :accordion="true"/>
* 否则部分平台(快手)可能获取到的 accordion 是空字符串
* @param param0
*/
function processBooleanAttr({ props }) {
props.forEach((prop, index) => {
if (prop.type === compiler_core_1.NodeTypes.ATTRIBUTE &&
typeof prop.value === 'undefined') {
props.splice(index, 1, (0, uni_cli_shared_1.createBindDirectiveNode)(prop.name, 'true'));
}
});
}
const builtInProps = [
// 'id',
'class',
'style',
utils_1.ATTR_VUE_ID,
utils_1.ATTR_VUE_PROPS,
utils_1.ATTR_VUE_SLOTS,
utils_1.ATTR_VUE_REF,
utils_1.ATTR_VUE_REF_IN_FOR,
utils_1.ATTR_COM_TYPE,
utils_1.ATTR_ELEMENT_ID,
utils_1.ATTR_SET_ELEMENT_STYLE,
'eO',
'e-o',
'onVI',
'ref',
'slot',
'key',
'is',
];
function isComponentProp(name) {
if (builtInProps.includes(name)) {
return false;
}
if (name.startsWith('data-')) {
return false;
}
if (name === (0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_STYLE)) {
return false;
}
return true;
}
/**
* 重写组件 props 绑定
* @param node
* @param context
*/
function rewriteBinding({ tag, props }, context) {
const isMiniProgramComponent = context.isMiniProgramComponent(tag);
if (isMiniProgramComponent === 'plugin' ||
isMiniProgramComponent === 'dynamicLib' ||
isMiniProgramComponent === 'xr-frame' ||
isMiniProgramComponent === 'ext') {
// 因无法介入插件类型组件内部实现,故保留原始属性
return;
}
const createObjectProperty = isMiniProgramComponent
? (name, value) => (0, types_1.objectProperty)((0, types_1.identifier)((0, shared_1.camelize)(name)), value)
: (name, value) => {
const computed = !(0, compiler_core_1.isSimpleIdentifier)(name);
return (0, types_1.objectProperty)(computed ? (0, types_1.stringLiteral)(name) : (0, types_1.identifier)(name), value, computed);
};
const properties = [];
for (let i = 0; i < props.length; i++) {
const prop = props[i];
let isIdProp = false;
if ((0, uni_cli_shared_1.isAttributeNode)(prop)) {
const { name } = prop;
isIdProp = name === 'id';
if (!isComponentProp(name)) {
continue;
}
properties.push(createObjectProperty(name, (0, types_1.stringLiteral)(prop.value?.content || '')));
}
else if ((0, uni_cli_shared_1.isDirectiveNode)(prop)) {
if (prop.name !== 'bind') {
continue;
}
const { arg, exp } = prop;
if (!exp) {
continue;
}
if (!arg) {
const spreadElement = createVBindSpreadElement(prop, context);
if (spreadElement) {
properties.push(spreadElement);
}
}
else if ((0, compiler_core_1.isStaticExp)(arg)) {
isIdProp = arg.content === 'id';
if (!isComponentProp(arg.content)) {
continue;
}
// :name="name"
const valueExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
if (!valueExpr) {
continue;
}
properties.push(createObjectProperty(arg.content, valueExpr));
}
else {
// :[dynamic]="dynamic"
const leftExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(arg), context, exp);
if (!leftExpr) {
continue;
}
const valueExpr = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
if (!valueExpr) {
continue;
}
properties.push((0, types_1.objectProperty)((0, types_1.logicalExpression)('||', leftExpr, (0, types_1.stringLiteral)('')), valueExpr, true));
}
}
// 即保留 id 属性,又补充到 props 中
if (!isIdProp) {
props.splice(i, 1);
i--;
}
}
if (properties.length) {
props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_PROPS, (0, codegen_1.genBabelExpr)((0, types_1.objectExpression)(properties))));
}
}
exports.rewriteBinding = rewriteBinding;
function createVBindSpreadElement(prop, context) {
const { arg, exp } = prop;
if (!exp) {
return;
}
if (!arg) {
const argument = (0, ast_1.parseExpr)((0, codegen_1.genExpr)(exp), context, exp);
if (!argument) {
return;
}
return (0, types_1.spreadElement)(argument);
}
}
function isPropsBinding({ arg }) {
return (arg &&
arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
arg.content === utils_1.ATTR_VUE_PROPS);
}
exports.isPropsBinding = isPropsBinding;
function rewritePropsBinding(dir, node, context) {
dir.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)((0, utils_1.rewirteWithHelper)(runtimeHelpers_1.RENDER_PROPS, (0, ast_1.parseExpr)(dir.exp, context), dir.loc, context)) +
(((0, vIf_1.isIfElementNode)(node) && node.vIf.name === 'else') ||
context.miniProgram.component?.getPropertySync
? `||''`
: ''));
}
exports.rewritePropsBinding = rewritePropsBinding;
@@ -0,0 +1,9 @@
import { type ElementNode, type Property, type TemplateLiteral } from '@vue/compiler-core';
import { type NodeTransform, type TransformContext } from '../transform';
export interface DirectiveTransformResult {
props: Property[];
needRuntime?: boolean | symbol;
ssrTagParts?: TemplateLiteral['elements'];
}
export declare const transformElement: NodeTransform;
export declare function processProps(node: ElementNode, context: TransformContext, props?: ElementNode['props']): void;
@@ -0,0 +1,200 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processProps = exports.transformElement = void 0;
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const uni_shared_1 = require("@dcloudio/uni-shared");
const errors_1 = require("../errors");
const vModel_1 = require("./vModel");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const transformElement = (node, context) => {
return function postTransformElement() {
node = context.currentNode;
if (!(node.type === compiler_core_1.NodeTypes.ELEMENT &&
(node.tagType === compiler_core_1.ElementTypes.ELEMENT ||
node.tagType === compiler_core_1.ElementTypes.COMPONENT))) {
return;
}
if (node.tagType === compiler_core_1.ElementTypes.COMPONENT) {
processComponent(node, context);
}
if (context.scopeId) {
addScopeId(node, context.scopeId);
}
const { props } = node;
if (props.length > 0) {
processProps(node, context);
}
};
};
exports.transformElement = transformElement;
function addScopeId(node, scopeId) {
return (0, uni_cli_shared_1.addStaticClass)(node, scopeId);
}
function processComponent(node, context) {
const { tag } = node;
if (context.bindingComponents[tag]) {
return;
}
// 1. dynamic component
if ((0, uni_shared_1.isComponentTag)(tag)) {
return context.onError((0, errors_1.createMPCompilerError)(8 /* MPErrorCodes.X_DYNAMIC_COMPONENT_NOT_SUPPORTED */, node.loc));
}
if ((0, compiler_core_1.findDir)(node, 'is')) {
return context.onError((0, errors_1.createMPCompilerError)(6 /* MPErrorCodes.X_V_IS_NOT_SUPPORTED */, node.loc));
}
// TODO not supported
// const isProp = findProp(node, 'is')
// if (isProp) {
// }
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
const builtIn = (0, compiler_core_1.isCoreComponent)(tag) || context.isBuiltInComponent(tag);
if (builtIn) {
return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
}
// 3. user component (from setup bindings)
const fromSetup = resolveSetupReference(tag, context);
if (fromSetup) {
return (context.bindingComponents[tag] = {
name: fromSetup,
type: "setup" /* BindingComponentTypes.SETUP */,
});
}
const dotIndex = tag.indexOf('.');
if (dotIndex > 0) {
return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
}
// 4. Self referencing component (inferred from filename)
if (context.selfName && (0, shared_1.capitalize)((0, shared_1.camelize)(tag)) === context.selfName) {
return (context.bindingComponents[tag] = {
name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
type: "self" /* BindingComponentTypes.SELF */,
});
}
// 5. user component (resolve)
context.bindingComponents[tag] = {
name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
type: "unknown" /* BindingComponentTypes.UNKNOWN */,
};
context.helper(compiler_core_1.RESOLVE_COMPONENT);
}
function resolveSetupReference(name, context) {
const bindings = context.bindingMetadata;
if (!bindings || bindings.__isScriptSetup === false) {
return;
}
const camelName = (0, shared_1.camelize)(name);
const PascalName = (0, shared_1.capitalize)(camelName);
const checkType = (type) => {
if (bindings[name] === type) {
return name;
}
if (bindings[camelName] === type) {
return camelName;
}
if (bindings[PascalName] === type) {
return PascalName;
}
};
const fromConst = checkType(compiler_core_1.BindingTypes.SETUP_CONST) ||
checkType(compiler_core_1.BindingTypes.SETUP_REACTIVE_CONST) ||
checkType(compiler_core_1.BindingTypes.LITERAL_CONST);
if (fromConst) {
return context.inline
? // in inline mode, const setup bindings (e.g. imports) can be used as-is
fromConst
: `$setup[${JSON.stringify(fromConst)}]`;
}
const fromMaybeRef = checkType(compiler_core_1.BindingTypes.SETUP_LET) ||
checkType(compiler_core_1.BindingTypes.SETUP_REF) ||
checkType(compiler_core_1.BindingTypes.SETUP_MAYBE_REF);
if (fromMaybeRef) {
return context.inline
? // setup scope bindings that may be refs need to be unrefed
`${context.helperString(compiler_core_1.UNREF)}(${fromMaybeRef})`
: `$setup[${JSON.stringify(fromMaybeRef)}]`;
}
}
function processProps(node, context, props = node.props) {
const { tag } = node;
const isComponent = node.tagType === compiler_core_1.ElementTypes.COMPONENT;
const isPluginComponent = isComponent && context.isMiniProgramComponent(node.tag) === 'plugin';
for (let i = 0; i < props.length; i++) {
const prop = props[i];
if (prop.type === compiler_core_1.NodeTypes.DIRECTIVE) {
// directives
const { name, arg, loc } = prop;
const isVBind = name === 'bind';
const isVOn = name === 'on';
// skip v-slot - it is handled by its dedicated transform.
if (name === 'slot') {
if (!isComponent) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_MISPLACED, loc));
}
continue;
}
// skip v-once/v-memo - they are handled by dedicated transforms.
if (name === 'once' || name === 'memo') {
continue;
}
// skip v-is and :is on <component>
if (name === 'is' ||
(isVBind && (0, compiler_core_1.isStaticArgOf)(arg, 'is') && (0, uni_shared_1.isComponentTag)(tag))) {
continue;
}
if (isVBind || isVOn) {
// v-on=""
// v-bind=""
if (!arg) {
if (isVOn) {
context.onError((0, errors_1.createMPCompilerError)(0 /* MPErrorCodes.X_V_ON_NO_ARGUMENT */, loc));
}
if (isVBind && (!isComponent || isPluginComponent)) {
context.onError((0, errors_1.createMPCompilerError)(2 /* MPErrorCodes.X_V_BIND_NO_ARGUMENT */, loc));
}
continue;
}
// v-on:[a]=""
// v-on:[a.b]=""
// v-bind:[a]=""
// v-bind:[a.b]=""
if (!(arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.isStatic)) {
if (isVOn) {
context.onError((0, errors_1.createMPCompilerError)(1 /* MPErrorCodes.X_V_ON_DYNAMIC_EVENT */, loc));
}
if (isVBind && (!isComponent || isPluginComponent)) {
context.onError((0, errors_1.createMPCompilerError)(3 /* MPErrorCodes.X_V_BIND_DYNAMIC_ARGUMENT */, loc));
}
continue;
}
}
const directiveTransform = context.directiveTransforms[name];
if (name !== 'model' && directiveTransform) {
const { props } = directiveTransform(prop, node, context);
if (props.length) {
prop.exp = props[0].value;
}
}
}
}
const transformVModel = (context.directiveTransforms.model ||
vModel_1.transformModel);
processVModel(node, transformVModel, context);
}
exports.processProps = processProps;
function processVModel(node, transformVModel, context) {
const { props } = node;
const dirs = [];
for (let i = 0; i < props.length; i++) {
const prop = props[i];
if (prop.type === compiler_core_1.NodeTypes.DIRECTIVE && prop.name === 'model') {
dirs.push(...transformVModel(prop, node, context)
.props);
props.splice(i, 1);
i--;
}
}
if (dirs.length) {
props.push(...dirs);
}
}
@@ -0,0 +1,5 @@
import { type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
import type { NodeTransform, TransformContext } from '../transform';
export declare const transformExpression: NodeTransform;
export declare function processExpression(node: SimpleExpressionNode, context: TransformContext, asParams?: boolean, asRawStatements?: boolean, localVars?: Record<string, number>): ExpressionNode;
export declare function isBuiltInIdentifier(id: string | ExpressionNode): boolean;
@@ -0,0 +1,299 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isBuiltInIdentifier = exports.processExpression = exports.transformExpression = void 0;
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const parser_1 = require("@babel/parser");
const isLiteralWhitelisted = /*#__PURE__*/ (0, shared_1.makeMap)('true,false,null,this');
const transformExpression = (node, context) => {
if (node.type === compiler_core_1.NodeTypes.INTERPOLATION) {
node.content = processExpression(node.content, context);
}
else if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
// handle directives on element
for (let i = 0; i < node.props.length; i++) {
const dir = node.props[i];
// do not process for v-on & v-for since they are special handled
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE && dir.name !== 'for') {
const exp = dir.exp;
const arg = dir.arg;
// do not process exp if this is v-on:arg - we need special handling
// for wrapping inline statements.
if (exp &&
exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
!(dir.name === 'on' && arg)) {
dir.exp = processExpression(exp, context,
// slot args must be processed as function params
dir.name === 'slot');
}
if (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
dir.arg = processExpression(arg, context);
}
}
}
}
};
exports.transformExpression = transformExpression;
// Important: since this function uses Node.js only dependencies, it should
// always be used with a leading !__BROWSER__ check so that it can be
// tree-shaken from the browser build.
function processExpression(node, context,
// some expressions like v-slot props & v-for aliases should be parsed as
// function params
asParams = false,
// v-on handler values may contain multiple statements
asRawStatements = false, localVars = Object.create(context.identifiers)) {
if (!context.prefixIdentifiers || !node.content.trim()) {
return node;
}
const { inline, bindingMetadata } = context;
const rewriteIdentifier = (raw, parent, id) => {
const type = (0, shared_1.hasOwn)(bindingMetadata, raw) && bindingMetadata[raw];
if (inline) {
// x = y
const isAssignmentLVal = parent && parent.type === 'AssignmentExpression' && parent.left === id;
// x++
const isUpdateArg = parent && parent.type === 'UpdateExpression' && parent.argument === id;
// ({ x } = y)
const isDestructureAssignment = parent && (0, compiler_core_1.isInDestructureAssignment)(parent, parentStack);
if (isConst(type) || localVars[raw]) {
return raw;
}
else if (type === compiler_core_1.BindingTypes.SETUP_REF) {
return `${raw}.value`;
}
else if (type === compiler_core_1.BindingTypes.SETUP_MAYBE_REF) {
// const binding that may or may not be ref
// if it's not a ref, then assignments don't make sense -
// so we ignore the non-ref assignment case and generate code
// that assumes the value to be a ref for more efficiency
return isAssignmentLVal || isUpdateArg || isDestructureAssignment
? `${raw}.value`
: `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
}
else if (type === compiler_core_1.BindingTypes.SETUP_LET) {
if (isAssignmentLVal) {
// let binding.
// this is a bit more tricky as we need to cover the case where
// let is a local non-ref value, and we need to replicate the
// right hand side value.
// x = y --> isRef(x) ? x.value = y : x = y
const { right: rVal, operator } = parent;
const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1);
const rExpString = stringifyExpression(processExpression((0, compiler_core_1.createSimpleExpression)(rExp, false), context, false, false, knownIds));
return `${context.helperString(compiler_core_1.IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${raw}.value ${operator} ${rExpString} : ${raw}`;
}
else if (isUpdateArg) {
// make id replace parent in the code range so the raw update operator
// is removed
id.start = parent.start;
id.end = parent.end;
const { prefix: isPrefix, operator } = parent;
const prefix = isPrefix ? operator : ``;
const postfix = isPrefix ? `` : operator;
// let binding.
// x++ --> isRef(a) ? a.value++ : a++
return `${context.helperString(compiler_core_1.IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`;
}
else if (isDestructureAssignment) {
// TODO
// let binding in a destructure assignment - it's very tricky to
// handle both possible cases here without altering the original
// structure of the code, so we just assume it's not a ref here
// for now
return raw;
}
else {
return `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
}
}
else if (type === compiler_core_1.BindingTypes.PROPS) {
// use __props which is generated by compileScript so in ts mode
// it gets correct type
return (0, shared_1.genPropsAccessExp)(raw);
}
else if (type === compiler_core_1.BindingTypes.PROPS_ALIASED) {
// prop with a different local alias (from defineProps() destructure)
return (0, shared_1.genPropsAccessExp)(bindingMetadata.__propsAliases[raw]);
}
}
else {
if ((type && type.startsWith('setup')) ||
type === compiler_core_1.BindingTypes.LITERAL_CONST) {
// setup bindings in non-inline mode
return `$setup.${raw}`;
}
else if (type === compiler_core_1.BindingTypes.PROPS_ALIASED) {
return `$props['${bindingMetadata.__propsAliases[raw]}']`;
}
else if (type) {
return `$${type}.${raw}`;
}
}
// fallback to ctx
return `_ctx.${raw}`;
};
// fast path if expression is a simple identifier.
const rawExp = node.content;
// bail constant on parens (function invocation) and dot (member access)
const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0;
if ((0, compiler_core_1.isSimpleIdentifier)(rawExp)) {
const isScopeVarReference = context.identifiers[rawExp];
const isAllowedGlobal = (0, shared_1.isGloballyWhitelisted)(rawExp);
const isLiteral = isLiteralWhitelisted(rawExp);
const isFilter = context.filters.includes(rawExp);
const isBuiltIn = isBuiltInIdentifier(rawExp);
if (!asParams &&
!isScopeVarReference &&
!isAllowedGlobal &&
!isLiteral &&
!isFilter &&
!isBuiltIn) {
// const bindings exposed from setup can be skipped for patching but
// cannot be hoisted to module scope
if (isConst(bindingMetadata[node.content])) {
node.constType = compiler_core_1.ConstantTypes.CAN_SKIP_PATCH;
}
node.content = rewriteIdentifier(rawExp);
}
else if (!isScopeVarReference) {
if (isLiteral) {
node.constType = compiler_core_1.ConstantTypes.CAN_STRINGIFY;
}
else {
node.constType = compiler_core_1.ConstantTypes.CAN_HOIST;
}
}
return node;
}
let ast;
// exp needs to be parsed differently:
// 1. Multiple inline statements (v-on, with presence of `;`): parse as raw
// exp, but make sure to pad with spaces for consistent ranges
// 2. Expressions: wrap with parens (for e.g. object expressions)
// 3. Function arguments (v-for, v-slot): place in a function argument position
const source = asRawStatements
? ` ${rawExp} `
: `(${rawExp})${asParams ? `=>{}` : ``}`;
try {
ast = (0, parser_1.parse)(source, {
plugins: context.expressionPlugins,
}).program;
}
catch (e) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_INVALID_EXPRESSION, node.loc, undefined, '\n' + source + '\n' + e.message));
return node;
}
const ids = [];
const parentStack = [];
const knownIds = Object.create(context.identifiers);
context.filters.forEach((name) => {
knownIds[name] = 1;
});
(0, compiler_core_1.walkIdentifiers)(ast, (node, parent, _, isReferenced, isLocal) => {
if ((0, compiler_core_1.isStaticPropertyKey)(node, parent)) {
return;
}
const needPrefix = isReferenced && canPrefix(node);
if (needPrefix && !isLocal) {
if ((0, compiler_core_1.isStaticProperty)(parent) && parent.shorthand) {
// property shorthand like { foo }, we need to add the key since
// we rewrite the value
;
node.prefix = `${node.name}: `;
}
node.name = rewriteIdentifier(node.name, parent, node);
ids.push(node);
}
else {
// The identifier is considered constant unless it's pointing to a
// local scope variable (a v-for alias, or a v-slot prop)
if (!(needPrefix && isLocal) && !bailConstant) {
;
node.isConstant = true;
}
// also generate sub-expressions for other identifiers for better
// source map support. (except for property keys which are static)
ids.push(node);
}
}, true, // invoke on ALL identifiers
parentStack, knownIds);
// We break up the compound expression into an array of strings and sub
// expressions (for identifiers that have been prefixed). In codegen, if
// an ExpressionNode has the `.children` property, it will be used instead of
// `.content`.
const children = [];
ids.sort((a, b) => a.start - b.start);
ids.forEach((id, i) => {
// range is offset by -1 due to the wrapping parens when parsed
const start = id.start - 1;
const end = id.end - 1;
const last = ids[i - 1];
const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);
if (leadingText.length || id.prefix) {
children.push(leadingText + (id.prefix || ``));
}
const source = rawExp.slice(start, end);
children.push((0, compiler_core_1.createSimpleExpression)(id.name, false, {
source,
start: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, start),
end: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, end),
}, id.isConstant ? compiler_core_1.ConstantTypes.CAN_STRINGIFY : compiler_core_1.ConstantTypes.NOT_CONSTANT));
if (i === ids.length - 1 && end < rawExp.length) {
children.push(rawExp.slice(end));
}
});
let ret;
if (children.length) {
ret = (0, compiler_core_1.createCompoundExpression)(children, node.loc);
}
else {
ret = node;
ret.constType = bailConstant
? compiler_core_1.ConstantTypes.NOT_CONSTANT
: compiler_core_1.ConstantTypes.CAN_STRINGIFY;
}
ret.identifiers = Object.keys(knownIds);
return ret;
}
exports.processExpression = processExpression;
function canPrefix(id) {
// skip whitelisted globals
if ((0, shared_1.isGloballyWhitelisted)(id.name)) {
return false;
}
// special case for webpack compilation
if (id.name === 'require') {
return false;
}
return true;
}
function stringifyExpression(exp) {
if ((0, shared_1.isString)(exp)) {
return exp;
}
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
return exp.content;
}
else {
return exp.children
.map(stringifyExpression)
.join('');
}
}
const builtInIdentifiers = ['__l'];
function isBuiltInIdentifier(id) {
if (!(0, shared_1.isString)(id)) {
if (id.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
return false;
}
id = id.content;
}
return builtInIdentifiers.includes(id);
}
exports.isBuiltInIdentifier = isBuiltInIdentifier;
function isConst(type) {
return (type === compiler_core_1.BindingTypes.SETUP_CONST ||
type === compiler_core_1.BindingTypes.LITERAL_CONST ||
type === compiler_core_1.BindingTypes.SETUP_REACTIVE_CONST);
}
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformIdentifier: NodeTransform;
@@ -0,0 +1,157 @@
"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 transformUniElement_1 = require("./transformUniElement");
const transformIdentifier = (node, context) => {
return function transformIdentifier() {
if (node.type === compiler_core_1.NodeTypes.INTERPOLATION) {
const content = node.content;
let isFilter = false;
if (content.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
const firstChild = content.children[0];
isFilter =
!(0, shared_1.isString)(firstChild) &&
!(0, shared_1.isSymbol)(firstChild) &&
firstChild.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
context.filters.includes(firstChild.content);
}
if (!isFilter) {
node.content = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
`${context.helperString(runtimeHelpers_1.TO_DISPLAY_STRING)}(`,
content,
`)`,
]), context);
}
}
else if ((0, compiler_core_1.isSlotOutlet)(node)) {
(0, transformSlot_1.rewriteSlot)(node, context);
}
else if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
let hasClassBinding = false;
let hasStyleBinding = false;
(0, transformRef_1.rewriteRef)(node, context);
if (context.isX) {
(0, transformUniElement_1.rewriteId)(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);
let elementId = '';
let skipIndex = [];
// 第一步:在 x 中,先处理 id 属性,用于提前获取 elementId 对应的变量名
if (context.isX) {
for (let i = 0; i < props.length; i++) {
const dir = props[i];
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE) {
const { arg, exp } = dir;
if (arg && exp && (0, uni_cli_shared_1.isSimpleExpressionNode)(arg)) {
if (arg.content === 'id' || arg.content === utils_1.ATTR_ELEMENT_ID) {
dir.exp = (0, utils_1.rewriteExpression)(exp, context);
elementId = dir.exp.content;
skipIndex.push(i);
}
}
}
}
}
for (let i = 0; i < props.length; i++) {
if (context.isX) {
// 已经处理过了
if (skipIndex.includes(i)) {
continue;
}
}
const dir = props[i];
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE) {
const arg = dir.arg;
if (arg) {
// TODO 指令暂不不支持动态参数,v-bind:[arg] v-on:[event]
if (!(arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.isStatic)) {
// v-slot:[slotName] 支持
if (dir.name === 'slot') {
(0, vSlot_1.rewriteVSlot)(dir, context);
}
else {
props.splice(i, 1);
i--;
continue;
}
}
}
const exp = dir.exp;
if (exp) {
if (isBuiltIn(dir)) {
// noop
}
else if ((0, transformClass_1.isClassBinding)(dir)) {
hasClassBinding = true;
(0, transformClass_1.rewriteClass)(i, dir, props, virtualHost, context);
}
else if ((0, transformStyle_1.isStyleBinding)(dir)) {
hasStyleBinding = true;
(0, transformStyle_1.rewriteStyle)(i, dir, props, virtualHost, context, elementId);
}
else if ((0, transformComponent_1.isPropsBinding)(dir)) {
(0, transformComponent_1.rewritePropsBinding)(dir, node, context);
}
else {
if (context.isX &&
elementId &&
arg &&
(0, uni_cli_shared_1.isSimpleExpressionNode)(arg) &&
arg.content === utils_1.ATTR_SET_ELEMENT_STYLE) {
dir.exp = (0, compiler_core_1.createSimpleExpression)(`$eS[${elementId}]`);
}
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 === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
builtInProps.includes(arg.content) &&
exp?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION);
}
@@ -0,0 +1,4 @@
import { type DirectiveNode } from '@vue/compiler-core';
import type { ForElementNode } from './vFor';
export declare function isSelfKey({ arg, exp }: DirectiveNode, vFor: ForElementNode['vFor'] | false): boolean | undefined;
export declare function rewriteSelfKey(dir: DirectiveNode): void;
+19
View File
@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteSelfKey = exports.isSelfKey = void 0;
const compiler_core_1 = require("@vue/compiler-core");
function isSelfKey({ arg, exp }, vFor) {
return (vFor &&
arg &&
exp &&
arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
arg.content === 'key' &&
exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
exp.content === vFor.valueAlias);
}
exports.isSelfKey = isSelfKey;
function rewriteSelfKey(dir) {
;
dir.exp.content = '*this';
}
exports.rewriteSelfKey = rewriteSelfKey;
@@ -0,0 +1,8 @@
import { type AttributeNode, type DirectiveNode, type ElementNode } from '@vue/compiler-core';
import type { TransformContext } from '../transform';
export declare function rewriteRef(node: ElementNode, context: TransformContext): void;
export declare function parseRefCode(prop: AttributeNode | DirectiveNode, context: TransformContext): {
code: string;
refKey: string;
};
export declare function rewriteRefProp(helper: symbol, prop: AttributeNode | DirectiveNode, idProp: AttributeNode | DirectiveNode, opts: Record<string, any>, context: TransformContext): void;
+126
View File
@@ -0,0 +1,126 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteRefProp = exports.parseRefCode = exports.rewriteRef = void 0;
const types_1 = require("@babel/types");
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const utils_1 = require("./utils");
const runtimeHelpers_1 = require("../runtimeHelpers");
const codegen_1 = require("../codegen");
const ast_1 = require("../ast");
function rewriteRef(node, context) {
const vueIdProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_ID);
if (!vueIdProp) {
return;
}
const refProp = (0, compiler_core_1.findProp)(node, 'u-' + uni_cli_shared_1.VUE_REF) || (0, compiler_core_1.findProp)(node, 'u-' + uni_cli_shared_1.VUE_REF_IN_FOR);
if (!refProp) {
return;
}
if ((0, compiler_core_1.findProp)(node, 'ref')) {
// 支付宝小程序
const code = parseAlipayRefCode(refProp, context);
if (code && context.inline && !(0, uni_cli_shared_1.isDirectiveNode)(refProp)) {
refProp.value.content = code;
const refPropIndex = node.props.findIndex((prop) => prop === refProp);
node.props.splice(refPropIndex, 1, (0, uni_cli_shared_1.createBindDirectiveNode)(refProp.name, code));
}
}
else {
rewriteRefProp(runtimeHelpers_1.SET_REF, refProp, vueIdProp, {}, context);
}
}
exports.rewriteRef = rewriteRef;
function parseRef(prop, context) {
let expr;
let refKey = '';
const isDir = (0, uni_cli_shared_1.isDirectiveNode)(prop);
if (isDir) {
if (prop.exp) {
expr = (0, ast_1.parseExpr)(prop.exp, context, prop.exp);
}
}
else {
const { value } = prop;
if (value && value.content) {
if (context.inline && context.bindingMetadata[value.content]) {
expr = (0, types_1.identifier)(value.content);
refKey = value.content;
}
else {
expr = (0, types_1.stringLiteral)(value.content);
}
}
}
return { expr, refKey };
}
function parseRefCode(prop, context) {
const { expr, refKey } = parseRef(prop, context);
if (!expr) {
return { code: '', refKey };
}
return { code: (0, codegen_1.genBabelExpr)(expr), refKey };
}
exports.parseRefCode = parseRefCode;
function rewriteRefProp(helper, prop, idProp, opts, context) {
let id = '';
if ((0, uni_cli_shared_1.isDirectiveNode)(idProp)) {
const vueIdExpr = (0, ast_1.parseExpr)(idProp.exp, context, idProp.exp);
if (vueIdExpr) {
id = (0, codegen_1.genBabelExpr)(vueIdExpr);
}
}
else {
id = `'${idProp.value.content}'`;
}
if (!id) {
return;
}
const { code, refKey } = parseRefCode(prop, context);
if (refKey) {
opts.k = refKey;
}
if (context.inVFor) {
opts.f = 1;
}
(0, utils_1.parseExprWithRewrite)(context.helperString(helper) +
'(' +
code +
', ' +
id +
(Object.keys(opts).length ? ', ' + JSON.stringify(opts) : '') +
')', prop.loc, context);
}
exports.rewriteRefProp = rewriteRefProp;
function parseAlipayRefCode(prop, context) {
let expr;
const isDir = (0, uni_cli_shared_1.isDirectiveNode)(prop);
if (isDir) {
if (prop.exp) {
expr = (0, ast_1.parseExpr)(prop.exp, context, prop.exp);
}
}
else {
if (prop.value?.content) {
expr = context.inline
? processInlineRef(prop, context)
: (0, types_1.stringLiteral)(prop.value.content);
}
}
if (!expr) {
return;
}
return (0, codegen_1.genBabelExpr)(expr);
}
function processInlineRef(prop, context) {
const properties = [];
const { refKey } = parseRef(prop, context);
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('r'), (0, types_1.identifier)(prop.value.content)));
if (refKey) {
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('k'), (0, types_1.stringLiteral)(refKey)));
}
if (context.inVFor) {
properties.push((0, types_1.objectProperty)((0, types_1.identifier)('f'), (0, types_1.numericLiteral)(1)));
}
return (0, types_1.arrowFunctionExpression)([], (0, types_1.objectExpression)(properties));
}
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformRoot: NodeTransform;
@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformRoot = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const ast_1 = require("../ast");
const types_1 = require("@babel/types");
const codegen_1 = require("../codegen");
const transformRoot = (node, context) => {
if (node.type !== compiler_core_1.NodeTypes.ROOT) {
return;
}
if (context.bindingCssVars.length) {
node.children.forEach((child) => {
if (child.type !== compiler_core_1.NodeTypes.ELEMENT) {
return;
}
addCssVars(child, context);
});
}
};
exports.transformRoot = transformRoot;
const CSS_VARS = '__cssVars()';
function addCssVars(node, context) {
const styleProp = (0, compiler_core_1.findProp)(node, 'style', true);
if (!styleProp) {
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('style', CSS_VARS));
}
else {
if (styleProp.exp?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
let expr = (0, ast_1.parseExpr)(styleProp.exp.content, context);
if ((0, types_1.isArrayExpression)(expr)) {
expr.elements.push((0, types_1.identifier)(CSS_VARS));
}
else {
expr = (0, types_1.arrayExpression)([expr, (0, types_1.identifier)(CSS_VARS)]);
}
styleProp.exp.content = (0, codegen_1.genBabelExpr)(expr);
}
}
}
@@ -0,0 +1,7 @@
import { type DirectiveNode, type SlotOutletNode } from '@vue/compiler-core';
import { type TransformContext } from '../transform';
export declare function rewriteSlot(node: SlotOutletNode, context: TransformContext): void;
export interface NameScopedSlotDirectiveNode extends DirectiveNode {
slotName: string;
}
export declare function parseVForKeyAlias(context: TransformContext): string[];
+188
View File
@@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseVForKeyAlias = exports.rewriteSlot = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const shared_1 = require("@vue/shared");
const uni_shared_1 = require("@dcloudio/uni-shared");
const runtimeHelpers_1 = require("../runtimeHelpers");
const codegen_1 = require("../codegen");
const transform_1 = require("../transform");
const transformElement_1 = require("./transformElement");
const utils_1 = require("./utils");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const __1 = require("..");
const ast_1 = require("../ast");
function rewriteSlot(node, context) {
let slotName = `"${uni_shared_1.SLOT_DEFAULT_NAME}"`;
let hasOtherDir = false;
const nonNameProps = [];
const { props } = node;
// 默认插槽强制设置name
if (!(0, compiler_core_1.findProp)(node, 'name')) {
props.unshift((0, uni_cli_shared_1.createAttributeNode)('name', 'default'));
}
for (let i = 0; i < props.length; i++) {
const p = props[i];
if (p.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
if (p.value) {
if (p.name === 'name') {
p.value.content = (0, uni_shared_1.dynamicSlotName)(p.value.content);
slotName = JSON.stringify(p.value.content);
}
else {
p.name = (0, shared_1.camelize)(p.name);
nonNameProps.push(p);
}
}
}
else {
if (p.name !== 'bind') {
hasOtherDir = true;
}
if (p.name === 'bind' && (0, compiler_core_1.isStaticArgOf)(p.arg, 'name')) {
if (p.exp) {
slotName = (0, compiler_core_1.createCompoundExpression)([
context.helperString(__1.DYNAMIC_SLOT) + '(',
p.exp,
')',
]);
let slotKey;
const keys = parseVForKeyAlias(context);
if (keys.length) {
const babelNode = (0, ast_1.parseExpr)(p.exp, context);
// 在 v-for 中,判断是否插槽名使用 v-for 的 key 变量
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, keys)) {
slotKey = parseScopedSlotKey(context);
}
}
p.exp = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
context.helperString(__1.DYNAMIC_SLOT) + '(',
p.exp,
slotKey ? `+'-'+` + slotKey : '',
')',
]), context);
}
}
else {
if (p.name === 'bind' && p.arg && (0, compiler_core_1.isStaticExp)(p.arg)) {
p.arg.content = (0, shared_1.camelize)(p.arg.content);
}
nonNameProps.push(p);
}
}
}
if (hasOtherDir) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET, node.loc));
}
if (nonNameProps.length > 0) {
(0, transformElement_1.processProps)(node, context, nonNameProps);
const properties = [];
nonNameProps.forEach((prop) => {
const property = transformProperty(prop, context);
property && properties.push(property);
});
if (properties.length) {
transformScopedSlotName(node, context);
const vForIndexAlias = parseVForIndexAlias(context);
(0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.RENDER_SLOT) + '(',
slotName,
',',
`{${properties.join(',')}}`,
`${vForIndexAlias ? ',' + parseScopedSlotKey(context) : ''}`,
')',
]), context);
}
else {
// 非作用域默认插槽直接移除命名
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
(0, utils_1.removeAttribute)(node, 'name');
}
}
}
else {
// 非作用域默认插槽直接移除命名
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
(0, utils_1.removeAttribute)(node, 'name');
}
}
}
exports.rewriteSlot = rewriteSlot;
function parseVForIndexAlias(context) {
let { currentScope } = context;
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
return currentScope.indexAlias;
}
currentScope = currentScope.parent;
}
}
function transformScopedSlotName(node, context) {
if (!context.miniProgram.slot.dynamicSlotNames) {
return;
}
const slotKey = parseScopedSlotKey(context);
if (!slotKey) {
return;
}
const nameProps = (0, compiler_core_1.findProp)(node, 'name');
if (nameProps && nameProps.type === compiler_core_1.NodeTypes.ATTRIBUTE && nameProps.value) {
const { props } = node;
props.splice(props.indexOf(nameProps), 1, createScopedSlotDirectiveNode(nameProps.value.content, slotKey, context));
}
}
function createScopedSlotDirectiveNode(name, slotKey, context) {
const dir = (0, uni_cli_shared_1.createBindDirectiveNode)('name', (0, utils_1.rewriteExpression)((0, compiler_core_1.createSimpleExpression)(`"${name}-"+` + slotKey), context)
.content);
// 存储原始的 slot 名称
dir.slotName = name;
return dir;
}
function parseVForKeyAlias(context) {
let { currentScope } = context;
const keys = [];
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
keys.push(currentScope.keyAlias);
}
currentScope = currentScope.parent;
}
return keys;
}
exports.parseVForKeyAlias = parseVForKeyAlias;
function parseVForIndexes(context) {
let { currentScope } = context;
const indexes = [];
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
indexes.push(currentScope.indexAlias);
}
currentScope = currentScope.parent;
}
return indexes;
}
function parseSlotKeyByVForIndexes(indexes) {
return indexes.reverse().join(`+'-'+`);
}
function parseScopedSlotKey(context) {
const indexes = parseVForIndexes(context);
const inFor = !!indexes.length;
if (inFor) {
return parseSlotKeyByVForIndexes(indexes);
}
}
function transformProperty(dir, _) {
if ((0, uni_cli_shared_1.isDirectiveNode)(dir)) {
if (!dir.arg || !dir.exp) {
return;
}
const isStaticArg = dir.arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && dir.arg.isStatic;
if (isStaticArg) {
return `${dir.arg.content}:${(0, codegen_1.genExpr)(dir.exp)}`;
}
return `[${(0, codegen_1.genExpr)(dir.arg)}||'']:${(0, codegen_1.genExpr)(dir.exp)}`;
}
if (dir.value) {
return `${dir.name}:${(0, codegen_1.genExpr)(dir.value)}`;
}
}
@@ -0,0 +1,6 @@
import { type AttributeNode, type DirectiveNode } from '@vue/compiler-core';
import type { TransformContext } from '../transform';
export declare function isStyleBinding({ arg, exp }: DirectiveNode): boolean | undefined;
export declare function findStaticStyleIndex(props: (AttributeNode | DirectiveNode)[]): number;
export declare function rewriteStyle(index: number, styleBindingProp: DirectiveNode, props: (AttributeNode | DirectiveNode)[], virtualHost: boolean, context: TransformContext, elementId?: string): void;
export declare function createVirtualHostStyle(props: (AttributeNode | DirectiveNode)[], context: TransformContext): DirectiveNode;
@@ -0,0 +1,189 @@
"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 === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && arg.content === 'style');
}
exports.isStyleBinding = isStyleBinding;
function findStaticStyleIndex(props) {
return props.findIndex((prop) => prop.name === 'style');
}
exports.findStaticStyleIndex = findStaticStyleIndex;
function rewriteStyle(index, styleBindingProp, props, virtualHost, context, elementId) {
const expr = styleBindingProp.exp
? (0, ast_1.parseExpr)(styleBindingProp.exp, context)
: undefined;
let styleBidingExpr = expr;
if (expr) {
if ((0, types_1.isObjectExpression)(expr)) {
styleBidingExpr = createStyleBindingByObjectExpression(rewriteStyleObjectExpression(expr, styleBindingProp.loc, context));
}
else if ((0, types_1.isArrayExpression)(expr)) {
styleBidingExpr = createStyleBindingByArrayExpression(rewriteStyleArrayExpression(expr, context));
}
else {
// 在 x 中,如果有 id 且不支持 setStyle
if (elementId &&
context.isX &&
!context.miniProgram.filter?.setStyle &&
(0, uni_cli_shared_1.isCompoundExpressionNode)(styleBindingProp.exp)) {
rewriteStyleExpression(styleBindingProp.exp, context);
styleBidingExpr = (0, ast_1.parseExpr)(`$eS[${elementId}]`, context);
}
else {
styleBidingExpr = (0, ast_1.parseExpr)(rewriteStyleExpression(styleBindingProp.exp, context).content, context);
}
}
if (!styleBidingExpr) {
return;
}
}
else if (!virtualHost) {
return;
}
const staticStylePropIndex = findStaticStyleIndex(props);
if (staticStylePropIndex > -1) {
const staticStyle = props[staticStylePropIndex].value
.content;
if (staticStyle.trim()) {
if (styleBidingExpr) {
if (index > staticStylePropIndex) {
styleBidingExpr = (0, types_1.binaryExpression)('+', addSemicolon((0, types_1.stringLiteral)(staticStyle)), styleBidingExpr);
}
else {
styleBidingExpr = (0, types_1.binaryExpression)('+', addSemicolon(styleBidingExpr), (0, types_1.stringLiteral)(staticStyle));
}
}
else {
styleBidingExpr = (0, types_1.stringLiteral)(staticStyle);
}
}
}
if (virtualHost) {
styleBidingExpr = styleBidingExpr
? (0, types_1.binaryExpression)('+', addSemicolon(styleBidingExpr), (0, types_1.identifier)(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;
}
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformTag: NodeTransform;
+17
View File
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformTag = void 0;
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const compiler_core_1 = require("@vue/compiler-core");
const transformTag = (node, _) => {
if (!(0, uni_cli_shared_1.isElementNode)(node) ||
(_ && _.isCustomElement && _.isCustomElement(node.tag))) {
return;
}
const newTag = uni_cli_shared_1.HTML_TO_MINI_PROGRAM_TAGS[node.tag];
if (newTag) {
node.tag = newTag;
node.tagType = compiler_core_1.ElementTypes.ELEMENT;
}
};
exports.transformTag = transformTag;
@@ -0,0 +1,3 @@
import { type ElementNode } from '@vue/compiler-core';
import type { TransformContext } from '../transform';
export declare function rewriteId(node: ElementNode, context: TransformContext): void;
@@ -0,0 +1,142 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteId = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const runtimeHelpers_1 = require("../runtimeHelpers");
const utils_1 = require("./utils");
const transformSlot_1 = require("./transformSlot");
const transformRef_1 = require("./transformRef");
const shared_1 = require("@vue/shared");
const builtInCustomElements = ['uni-cloud-db-element'];
const builtInComponents = ['unicloud-db'];
function rewriteId(node, context) {
const isUniElement = !(0, uni_cli_shared_1.isUserComponent)(node, context);
const origTagName = node.tag;
const isBuiltInComponent = !isUniElement && builtInComponents.includes(origTagName);
const userComponent = !(isUniElement || isBuiltInComponent);
if (userComponent) {
// TODO 目前不对用户的自定义组件支持 id 查询 UniElement
// 后续要做的话,需要考虑自定义组件内部的单节点或多节点
return;
}
const isBuiltInCustomElement = builtInCustomElements.includes(origTagName);
if (isUniElement) {
// 将内置的自定义元素转换为 view
if (isBuiltInCustomElement) {
node.props.unshift((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_ELEMENT_TAG, origTagName));
node.tag = 'view';
}
}
// 内置组件使用了 ref,没有 id 时,自动补充一个
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
if (refProp && !(0, compiler_core_1.findProp)(node, 'id')) {
if (context.inVFor) {
// v-for 中的 ref 需要使用 v-for 的 key 作为 id
const keyAlias = (0, transformSlot_1.parseVForKeyAlias)(context);
// 微信小程序元素id必须以字母开头,所以hashId不能放到前边,它可能是数字开头
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId + '-';
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([`'${id}'+`, keyAlias.join(`+'-'+`)])));
}
else {
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId;
node.props.push((0, uni_cli_shared_1.createAttributeNode)('id', id));
}
}
const idProp = (0, compiler_core_1.findProp)(node, 'id');
if (!idProp) {
return;
}
let idOptions = origTagName;
if (isBuiltInComponent || isBuiltInCustomElement) {
idOptions = {
name: origTagName,
type: isBuiltInComponent
? 1 /* SetUniElementIdTagType.BuiltInComponent */
: 2 /* SetUniElementIdTagType.BuiltInRootElement */,
};
}
let idExprNode;
// id="test" => :id="setUniElementId('test')"
// 目前标签名有隐患,可能传入的是自定义组件名称
if ((0, uni_cli_shared_1.isAttributeNode)(idProp)) {
if (!idProp.value) {
return;
}
idExprNode = `'${idProp.value.content}'`;
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_ELEMENT_ID, (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
idExprNode,
',',
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
parseUniElementRefCode(node, context),
')',
])));
}
else if (idProp.exp) {
idExprNode = idProp.exp;
const idPropIndex = node.props.indexOf(idProp);
// :id="a" => :id="setUniElementId(a)"
node.props.splice(idPropIndex, 1, (0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
idExprNode,
',',
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
parseUniElementRefCode(node, context),
')',
])));
}
if (context.miniProgram.filter?.setStyle) {
// 支持通过filter来设置style
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)((0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_STYLE), (0, utils_1.filterName)(utils_1.FILTER_SET_ELEMENT_STYLE)));
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_SET_ELEMENT_STYLE, ''));
if (!context.autoImportFilters.find((filter) => filter.name === utils_1.FILTER_MODULE_NAME)) {
context.autoImportFilters.push({
name: utils_1.FILTER_MODULE_NAME,
id: utils_1.FILTER_MODULE_FILE_NAME,
type: 'filter',
});
}
}
else {
// 如果没有动态绑定 style,则创建一个新的
const styleProp = (0, compiler_core_1.findProp)(node, 'style', true, true);
if (!styleProp) {
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('style', (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
idExprNode,
')',
])));
}
else {
// 传递已绑定的 style
styleProp.exp = (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
idExprNode,
',',
styleProp.exp,
')',
]);
}
}
}
exports.rewriteId = rewriteId;
function parseUniElementRefCode(node, context) {
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
if (!refProp) {
return '';
}
const { code, refKey } = (0, transformRef_1.parseRefCode)(refProp, context);
const opts = {};
if (refKey) {
opts.k = refKey;
}
if (context.inVFor) {
opts.f = 1;
}
const children = [',', code];
if (Object.keys(opts).length) {
children.push(',', JSON.stringify(opts));
}
return (0, compiler_core_1.createCompoundExpression)(children);
}
+35
View File
@@ -0,0 +1,35 @@
import { type Expression, type Identifier, type MemberExpression, type Node, type SpreadElement } from '@babel/types';
import { type ElementNode, type ExpressionNode, type SimpleExpressionNode, type SourceLocation, type TransformContext as VueTransformContext } from '@vue/compiler-core';
import type { CodegenScope } from '../options';
import { type TransformContext } from '../transform';
export declare const ATTR_VUE_ID = "u-i";
export declare const ATTR_VUE_SLOTS = "u-s";
export declare const ATTR_VUE_PROPS = "u-p";
export declare const ATTR_VUE_REF: string;
export declare const ATTR_VUE_REF_IN_FOR: string;
export declare const ATTR_COM_TYPE = "u-t";
export declare const ATTR_ELEMENT_ID = "u-e";
export declare const ATTR_ELEMENT_TAG = "u-t";
export declare const ATTR_SET_ELEMENT_STYLE = "eS";
export declare const FILTER_MODULE_NAME = "uV";
export declare const FILTER_MODULE_FILE_NAME = "uniView";
export declare const FILTER_SET_ELEMENT_STYLE = "sS";
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 filterObserverName(name: string): string;
export declare function filterName(name: string): string;
export declare function rewriteSpreadElement(name: symbol, expr: SpreadElement, loc: SourceLocation, context: TransformContext): Identifier | MemberExpression | undefined;
export declare function rewirteWithHelper(name: symbol, expr: Expression, loc: SourceLocation, context: TransformContext): Identifier | MemberExpression | undefined;
export declare function parseExprWithRewrite(code: string, loc: SourceLocation, context: TransformContext, node?: Expression): Identifier | MemberExpression | undefined;
export declare function parseExprWithRewriteClass(code: string, loc: SourceLocation, context: TransformContext, node: Expression): Identifier | MemberExpression | undefined;
export declare function rewriteExpressionWithoutProperty(node: ExpressionNode, context: TransformContext, babelNode?: Expression, scope?: CodegenScope): SimpleExpressionNode;
export declare function rewriteExpression(node: ExpressionNode, context: TransformContext | VueTransformContext, babelNode?: Expression, scope?: CodegenScope, { property, ignoreLiteral, referencedScope, }?: {
property: boolean;
ignoreLiteral: boolean;
referencedScope?: CodegenScope;
}): SimpleExpressionNode;
export declare function findReferencedScope(node: Expression, scope: CodegenScope, findReferenced?: boolean): CodegenScope;
export declare function isReferencedByIds(node: Expression, knownIds: string[]): boolean;
export declare function isStaticLiteral(value: Node | null | undefined): boolean;
export declare function removeAttribute(node: ElementNode, name: string): void;
+151
View File
@@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeAttribute = exports.isStaticLiteral = exports.isReferencedByIds = exports.findReferencedScope = exports.rewriteExpression = exports.rewriteExpressionWithoutProperty = exports.parseExprWithRewriteClass = exports.parseExprWithRewrite = exports.rewirteWithHelper = exports.rewriteSpreadElement = exports.filterName = exports.filterObserverName = exports.VIRTUAL_HOST_CLASS = exports.VIRTUAL_HOST_STYLE = exports.SCOPED_SLOT_IDENTIFIER = exports.FILTER_SET_ELEMENT_STYLE = exports.FILTER_MODULE_FILE_NAME = exports.FILTER_MODULE_NAME = exports.ATTR_SET_ELEMENT_STYLE = exports.ATTR_ELEMENT_TAG = exports.ATTR_ELEMENT_ID = exports.ATTR_COM_TYPE = exports.ATTR_VUE_REF_IN_FOR = exports.ATTR_VUE_REF = exports.ATTR_VUE_PROPS = exports.ATTR_VUE_SLOTS = exports.ATTR_VUE_ID = void 0;
const types_1 = require("@babel/types");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const compiler_core_1 = require("@vue/compiler-core");
const estree_walker_1 = require("estree-walker");
const ast_1 = require("../ast");
const codegen_1 = require("../codegen");
const transform_1 = require("../transform");
// v-i,v-s 不能在 quickapp-webview 中使用,估计是内部处理成了指令之类的
exports.ATTR_VUE_ID = 'u-i';
exports.ATTR_VUE_SLOTS = 'u-s';
exports.ATTR_VUE_PROPS = 'u-p';
exports.ATTR_VUE_REF = 'u-' + uni_cli_shared_1.VUE_REF;
exports.ATTR_VUE_REF_IN_FOR = 'u-' + uni_cli_shared_1.VUE_REF_IN_FOR;
exports.ATTR_COM_TYPE = 'u-t';
exports.ATTR_ELEMENT_ID = 'u-e';
exports.ATTR_ELEMENT_TAG = 'u-t';
exports.ATTR_SET_ELEMENT_STYLE = 'eS'; // 不能使用连字符e-s
exports.FILTER_MODULE_NAME = 'uV'; // uniView
exports.FILTER_MODULE_FILE_NAME = 'uniView';
exports.FILTER_SET_ELEMENT_STYLE = 'sS'; // setStyle
exports.SCOPED_SLOT_IDENTIFIER = '__SCOPED_SLOT__';
exports.VIRTUAL_HOST_STYLE = 'virtualHostStyle';
exports.VIRTUAL_HOST_CLASS = 'virtualHostClass';
function filterObserverName(name) {
return 'change:' + name;
}
exports.filterObserverName = filterObserverName;
function filterName(name) {
return exports.FILTER_MODULE_NAME + '.' + name;
}
exports.filterName = filterName;
function rewriteSpreadElement(name, expr, loc, context) {
return rewirteWithHelper(name, expr.argument, loc, context);
}
exports.rewriteSpreadElement = rewriteSpreadElement;
function rewirteWithHelper(name, expr, loc, context) {
return parseExprWithRewrite(context.helperString(name) + '(' + (0, codegen_1.genBabelExpr)(expr) + ')', loc, context);
}
exports.rewirteWithHelper = rewirteWithHelper;
function parseExprWithRewrite(code, loc, context, node) {
return (0, ast_1.parseExpr)(rewriteExpression((0, compiler_core_1.createSimpleExpression)(code, false, loc), context, node), context);
}
exports.parseExprWithRewrite = parseExprWithRewrite;
function parseExprWithRewriteClass(code, loc, context, node) {
// a?1:0
return (0, ast_1.parseExpr)(rewriteExpression((0, compiler_core_1.createSimpleExpression)(code, false, loc), context, !(0, ast_1.isUndefined)(node)
? (0, types_1.conditionalExpression)(node, (0, types_1.numericLiteral)(1), (0, types_1.stringLiteral)(''))
: node), context);
}
exports.parseExprWithRewriteClass = parseExprWithRewriteClass;
function rewriteExpressionWithoutProperty(node, context, babelNode, scope = context.currentScope) {
return rewriteExpression(node, context, babelNode, scope, {
property: false,
ignoreLiteral: false,
});
}
exports.rewriteExpressionWithoutProperty = rewriteExpressionWithoutProperty;
function rewriteExpression(node, context, babelNode, scope = context.currentScope, { property, ignoreLiteral, referencedScope, } = {
property: true,
ignoreLiteral: false,
}) {
if (node.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && node.isStatic) {
return node;
}
if (!babelNode) {
const code = (0, codegen_1.genExpr)(node);
babelNode = (0, ast_1.parseExpr)(code, context, node);
if (!babelNode) {
return (0, compiler_core_1.createSimpleExpression)(code);
}
}
if (!ignoreLiteral && isStaticLiteral(babelNode)) {
return node;
}
if ((0, ast_1.isUndefined)(babelNode)) {
return (0, compiler_core_1.createSimpleExpression)('undefined', false, node.loc);
}
// wxs 等表达式
if (context.filters?.length) {
if (isReferencedByIds(babelNode, context.filters)) {
return (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genExpr)(node), false, node.loc);
}
}
referencedScope = referencedScope || findReferencedScope(babelNode, scope);
const id = referencedScope.id.next();
if (property) {
referencedScope.properties.push((0, types_1.objectProperty)((0, types_1.identifier)(id), babelNode));
}
// 在 v-for 中包含的 v-if 块,所有变量需要补充当前 v-for value 前缀
if ((0, transform_1.isVIfScope)(referencedScope)) {
if ((0, transform_1.isVForScope)(referencedScope.parentScope)) {
return (0, compiler_core_1.createSimpleExpression)(referencedScope.parentScope.valueAlias + '.' + id);
}
return (0, compiler_core_1.createSimpleExpression)(id);
}
else if ((0, transform_1.isVForScope)(referencedScope)) {
return (0, compiler_core_1.createSimpleExpression)(referencedScope.valueAlias + '.' + id);
}
return (0, compiler_core_1.createSimpleExpression)(id);
}
exports.rewriteExpression = rewriteExpression;
function findReferencedScope(node, scope, findReferenced = true) {
if ((0, transform_1.isVIfScope)(scope)) {
return scope;
}
else if ((0, transform_1.isVForScope)(scope)) {
if (!findReferenced) {
return scope;
}
if (isReferencedByIds(node, scope.locals)) {
return scope;
}
return findReferencedScope(node, scope.parent, findReferenced);
}
return scope;
}
exports.findReferencedScope = findReferencedScope;
function isReferencedByIds(node, knownIds) {
let referenced = false;
(0, estree_walker_1.walk)(node, {
enter(node, parent) {
if (referenced) {
return this.skip();
}
if (!(0, types_1.isIdentifier)(node)) {
return;
}
if (knownIds.includes(node.name) &&
(!parent || (0, types_1.isReferenced)(node, parent))) {
referenced = true;
return this.skip();
}
},
});
return referenced;
}
exports.isReferencedByIds = isReferencedByIds;
function isStaticLiteral(value) {
return (0, types_1.isLiteral)(value) && !(0, types_1.isTemplateLiteral)(value);
}
exports.isStaticLiteral = isStaticLiteral;
function removeAttribute(node, name) {
const index = node.props.findIndex((prop) => prop.name === name);
if (index > -1) {
node.props.splice(index, 1);
}
}
exports.removeAttribute = removeAttribute;
+2
View File
@@ -0,0 +1,2 @@
import type { DirectiveTransform } from '../transform';
export declare const transformBind: DirectiveTransform;
+49
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 !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
arg.children.unshift(`(`);
arg.children.push(`) || ""`);
}
else if (!arg.isStatic) {
arg.content = `${arg.content} || ""`;
}
// .sync is replaced by v-model:arg
if (modifiers.includes('camel')) {
if (arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
if (arg.isStatic) {
arg.content = (0, shared_1.camelize)(arg.content);
}
else {
// arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`
}
}
else {
// arg.children.unshift(`${context.helperString(CAMELIZE)}(`)
// arg.children.push(`)`)
}
}
if (modifiers.includes('prop')) {
context[context.isX ? 'onError' : 'onWarn']((0, errors_1.createMPCompilerError)(4 /* MPErrorCodes.X_V_BIND_MODIFIER_PROP */, loc));
}
if (modifiers.includes('attr')) {
context[context.isX ? 'onError' : 'onWarn']((0, errors_1.createMPCompilerError)(5 /* MPErrorCodes.X_V_BIND_MODIFIER_ATTR */, loc));
}
if (!exp ||
(exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_BIND_NO_EXPRESSION, loc));
return {
props: [(0, compiler_core_1.createObjectProperty)(arg, (0, compiler_core_1.createSimpleExpression)('', true, loc))],
};
}
return {
props: [(0, compiler_core_1.createObjectProperty)(arg, exp)],
};
};
exports.transformBind = transformBind;
+37
View File
@@ -0,0 +1,37 @@
import { type ElementNode, ElementTypes, type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
import { type NodeTransform, type TransformContext } from '../transform';
import { type Expression, type Identifier, type Pattern, type RestElement } from '@babel/types';
import type { CodegenScope, CodegenVForScope } from '../options';
export type VForOptions = Omit<ForParseResult, 'tagType'> & {
sourceExpr?: Expression;
sourceAlias: string;
sourceCode: string;
valueCode: string;
valueExpr: Identifier | Pattern | RestElement;
valueAlias: string;
keyCode: string;
keyExpr: Identifier | Pattern | RestElement;
keyAlias: string;
indexCode: string;
indexExpr: Identifier | Pattern | RestElement;
indexAlias: string;
node: ElementNode;
};
export type ForElementNode = ElementNode & {
vFor: VForOptions & {
source: ExpressionNode;
};
};
export declare function isForElementNode(node: unknown): node is ForElementNode;
export declare const transformFor: NodeTransform;
export declare function parseVForScope(currentScope: CodegenScope): CodegenVForScope | undefined;
export interface ForParseResult {
source: ExpressionNode;
value: ExpressionNode;
key: ExpressionNode;
index: ExpressionNode;
tagType: ElementTypes;
}
export declare function parseForExpression(input: SimpleExpressionNode, context: TransformContext): ForParseResult | undefined;
export declare function createForLoopParams({ value, key, index }: ForParseResult, memoArgs?: ExpressionNode[]): ExpressionNode[];
export declare function createVForArrowFunctionExpression({ valueExpr, keyExpr, indexExpr, properties, }: CodegenVForScope): import("@babel/types").ArrowFunctionExpression;
+303
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)(compiler_core_1.ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc));
return;
}
const parseResult = parseForExpression(dir.exp, context);
if (!parseResult) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc));
return;
}
parseResult.tagType = node.tagType;
const { addIdentifiers, removeIdentifiers } = context;
const { source, value, key, index } = parseResult;
if (context.prefixIdentifiers) {
addIdentifiers(value);
addIdentifiers(key);
addIdentifiers(index);
}
const { currentScope: parentScope, scopes, popScope } = context;
const sourceExpr = (0, ast_1.parseExpr)(source, context);
const valueCode = (0, codegen_1.genExpr)(value);
const valueExpr = (0, ast_1.parseParam)(valueCode, context, value);
const valueAlias = parseAlias(valueExpr, valueCode, 'v' + scopes.vFor);
const keyCode = (0, codegen_1.genExpr)(key);
const keyExpr = (0, ast_1.parseParam)(keyCode, context, key);
const keyAlias = parseAlias(keyExpr, keyCode, 'k' + scopes.vFor);
const indexCode = (0, codegen_1.genExpr)(index);
const indexExpr = (0, ast_1.parseParam)(indexCode, context, index);
const indexAlias = parseAlias(indexExpr, indexCode, 'i' + scopes.vFor);
// 先占位 vFor,后续更新 cloneSourceExpr 为 CallExpression
const cloneSourceExpr = (0, types_1.cloneNode)(sourceExpr, false);
const sourceAliasReferencedScope = (0, utils_1.findReferencedScope)(cloneSourceExpr, context.currentScope,
// vFor 嵌套时,始终保持嵌套关系,issues/3263
false);
// 寻找子节点中 if 指令作用域
const vIfReferencedScope = findVIfReferencedScope(node, context.currentScope, context);
// 取最近的作用域
const referencedScope = vIfReferencedScope &&
context.getScopeIndex(vIfReferencedScope) >
context.getScopeIndex(sourceAliasReferencedScope)
? vIfReferencedScope
: sourceAliasReferencedScope;
const sourceAlias = (0, utils_1.rewriteExpression)(source, context, cloneSourceExpr, parentScope,
// 强制 rewrite,因为即使是字符串,数字,也要走 vFor 函数
{
property: true,
ignoreLiteral: true,
referencedScope,
}).content;
const sourceCode = `{{${sourceAlias}}}`;
const vForData = {
source,
sourceExpr,
sourceAlias,
sourceCode,
value,
valueCode,
valueExpr,
valueAlias,
key,
keyCode,
keyExpr,
keyAlias,
index,
indexCode,
indexExpr,
indexAlias,
node,
};
const vForScope = context.addVForScope({
...vForData,
locals: findVForLocals(parseResult),
});
const vFor = {
...vForData,
};
const isScopedSlot = (0, transform_1.isScopedSlotVFor)(vForScope);
node.vFor = vFor;
scopes.vFor++;
return () => {
scopes.vFor--;
if ((0, compiler_core_1.isTemplateNode)(node)) {
node.children.some((c) => {
if (c.type === compiler_core_1.NodeTypes.ELEMENT && !isForElementNode(c)) {
const key = (0, compiler_core_1.findProp)(c, 'key');
if (key) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT, key.loc));
return true;
}
}
});
}
if (context.prefixIdentifiers) {
value && removeIdentifiers(value);
key && removeIdentifiers(key);
index && removeIdentifiers(index);
}
(0, shared_1.extend)(clearExpr(cloneSourceExpr), isScopedSlot
? (0, vSlot_1.createVSlotCallExpression)(node
.slotComponent, vForScope, context)
: createVForCallExpression(vForScope, context));
popScope();
};
});
function clearExpr(expr) {
Object.keys(expr).forEach((key) => {
delete expr[key];
});
return expr;
}
function parseAlias(babelExpr, exprCode, fallback) {
if ((0, types_1.isIdentifier)(babelExpr)) {
return exprCode;
}
return fallback;
}
function parseVForScope(currentScope) {
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
return currentScope;
}
currentScope = currentScope.parent;
}
}
exports.parseVForScope = parseVForScope;
function findVIfReferencedScope(node, currentScope, context) {
if (!currentScope) {
return;
}
const vForScope = parseVForScope(currentScope);
if (!vForScope) {
return;
}
if (!node.children.find((item) => checkVIfReferenced(item, vForScope, context))) {
return findVIfReferencedScope(node, currentScope.parent, context);
}
return vForScope;
}
function checkVIfReferenced(node, vForScope, context) {
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
return false;
}
// 嵌套 for 不查找
if ((0, compiler_core_1.findDir)(node, 'for')) {
return false;
}
const ifDir = (0, compiler_core_1.findDir)(node, 'if');
if (ifDir) {
return checkDirReferenced(ifDir.exp, vForScope, context);
}
const elseIfDir = (0, compiler_core_1.findDir)(node, 'else-if');
if (elseIfDir) {
return checkDirReferenced(elseIfDir.exp, vForScope, context);
}
return !!node.children.find((item) => checkVIfReferenced(item, vForScope, context));
}
function checkDirReferenced(node, vForScope, context) {
if (node) {
const babelNode = (0, ast_1.parseExpr)(node, context);
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, vForScope.locals)) {
return true;
}
}
return false;
}
function findVForLocals({ value, key, index }) {
const ids = [];
if (value) {
findIds(value, ids);
}
if (key) {
findIds(key, ids);
}
if (index) {
findIds(index, ids);
}
return ids;
}
function findIds(exp, ids) {
if ((0, shared_1.isString)(exp)) {
ids.push(exp);
}
else if (exp.identifiers) {
exp.identifiers.forEach((id) => ids.push(id));
}
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
ids.push(exp.content);
}
}
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
const stripParensRE = /^\(|\)$/g;
function parseForExpression(input, context) {
const loc = input.loc;
const exp = input.content;
const inMatch = exp.match(forAliasRE);
if (!inMatch)
return;
const [, LHS, RHS] = inMatch;
const result = {
source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),
value: (0, compiler_core_1.createSimpleExpression)('v' + context.scopes.vFor),
key: (0, compiler_core_1.createSimpleExpression)('k' + context.scopes.vFor),
index: (0, compiler_core_1.createSimpleExpression)('i' + context.scopes.vFor),
tagType: compiler_core_1.ElementTypes.ELEMENT,
};
if (context.prefixIdentifiers) {
result.source = (0, transformExpression_1.processExpression)(result.source, context);
}
let valueContent = LHS.trim().replace(stripParensRE, '').trim();
const trimmedOffset = LHS.indexOf(valueContent);
const iteratorMatch = valueContent.match(forIteratorRE);
if (iteratorMatch) {
valueContent = valueContent.replace(forIteratorRE, '').trim();
const keyContent = iteratorMatch[1].trim();
let keyOffset;
if (keyContent) {
keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);
result.key = createAliasExpression(loc, keyContent, keyOffset);
if (context.prefixIdentifiers) {
result.key = (0, transformExpression_1.processExpression)(result.key, context, true);
}
}
if (iteratorMatch[2]) {
const indexContent = iteratorMatch[2].trim();
if (indexContent) {
result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key
? keyOffset + keyContent.length
: trimmedOffset + valueContent.length));
if (context.prefixIdentifiers) {
result.index = (0, transformExpression_1.processExpression)(result.index, context, true);
}
}
}
}
if (valueContent) {
result.value = createAliasExpression(loc, valueContent, trimmedOffset);
if (context.prefixIdentifiers) {
result.value = (0, transformExpression_1.processExpression)(result.value, context, true);
}
}
return result;
}
exports.parseForExpression = parseForExpression;
function createAliasExpression(range, content, offset) {
return (0, compiler_core_1.createSimpleExpression)(content, false, (0, uni_cli_shared_1.getInnerRange)(range, offset, content.length));
}
function createForLoopParams({ value, key, index }, memoArgs = []) {
return createParamsList([value, key, index, ...memoArgs]);
}
exports.createForLoopParams = createForLoopParams;
function createParamsList(args) {
let i = args.length;
while (i--) {
if (args[i])
break;
}
return args
.slice(0, i + 1)
.map((arg, i) => arg || (0, compiler_core_1.createSimpleExpression)(`_`.repeat(i + 1), false));
}
function createVForCallExpression(vForScope, context) {
// let sourceExpr: Expression = vForScope.sourceExpr!
// if (isNumericLiteral(sourceExpr)) {
// sourceExpr = numericLiteralToArrayExpr((sourceExpr as NumericLiteral).value)
// }
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.V_FOR)), [
vForScope.sourceExpr,
createVForArrowFunctionExpression(vForScope),
]);
}
function createVForArrowFunctionExpression({ valueExpr, keyExpr, indexExpr, properties, }) {
const params = [];
if (valueExpr) {
params.push(valueExpr);
}
if (keyExpr) {
params.push(keyExpr);
}
if (indexExpr) {
params.push(indexExpr);
}
return (0, types_1.arrowFunctionExpression)(params, (0, types_1.blockStatement)([(0, types_1.returnStatement)((0, types_1.objectExpression)(properties))]));
}
exports.createVForArrowFunctionExpression = createVForArrowFunctionExpression;
+2
View File
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformHtml: NodeTransform;
+35
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 !== compiler_core_1.ElementTypes.ELEMENT) {
return;
}
node.isSelfClosing = false;
node.children = [createRichText(node, dir)];
};
exports.transformHtml = transformHtml;
function createRichText(node, dir) {
return {
tag: 'rich-text',
type: compiler_core_1.NodeTypes.ELEMENT,
tagType: compiler_core_1.ElementTypes.ELEMENT,
props: [(0, uni_cli_shared_1.createBindDirectiveNode)('nodes', dir.exp || '')],
isSelfClosing: true,
children: [],
codegenNode: undefined,
ns: node.ns,
loc: node.loc,
};
}
+13
View File
@@ -0,0 +1,13 @@
import { type DirectiveNode, type ElementNode, type IfNode } from '@vue/compiler-core';
import { type NodeTransform, type TransformContext } from '../transform';
interface IfOptions {
name: string;
condition?: string;
}
export type IfElementNode = ElementNode & {
vIf: IfOptions;
};
export declare function isIfElementNode(node: unknown): node is IfElementNode;
export declare const transformIf: NodeTransform;
export declare function processIf(node: ElementNode, dir: DirectiveNode, context: TransformContext, processCodegen?: (node: IfNode, branch: IfElementNode, isRoot: boolean) => (() => void) | undefined): (() => void) | undefined;
export {};
+139
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)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
}
let alternate = (0, ast_1.createObjectExpression)([]);
if (dir.name === 'else-if') {
alternate = (0, ast_1.createVIfConditionalExpression)(vIfScope);
}
else if (dir.name === 'else') {
alternate = (0, ast_1.createObjectExpression)(vIfScope.properties);
}
findVIfConditionalExpression(vIfSpreadElement.argument).alternate = alternate;
}
popScope();
};
});
});
function processIf(node, dir, context, processCodegen) {
if (dir.name !== 'else' &&
(!dir.exp || !dir.exp.content.trim())) {
const loc = dir.exp ? dir.exp.loc : node.loc;
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc));
dir.exp = (0, compiler_core_1.createSimpleExpression)(`true`, false, loc);
}
if (context.prefixIdentifiers && dir.exp) {
// dir.exp can only be simple expression because vIf transform is applied
// before expression transform.
dir.exp = (0, transformExpression_1.processExpression)(dir.exp, context);
}
if (dir.name === 'if') {
const ifNode = {
type: compiler_core_1.NodeTypes.IF,
loc: node.loc,
branches: [node],
};
context.replaceNode(ifNode);
if (processCodegen) {
return processCodegen(ifNode, node, true);
}
}
else {
// locate the adjacent v-if
const siblings = context.parent.children;
let i = siblings.indexOf(node);
while (i-- >= -1) {
const sibling = siblings[i];
if (sibling && sibling.type === compiler_core_1.NodeTypes.COMMENT) {
context.removeNode(sibling);
continue;
}
if (sibling &&
sibling.type === compiler_core_1.NodeTypes.TEXT &&
!sibling.content.trim().length) {
context.removeNode(sibling);
continue;
}
if (sibling && sibling.type === compiler_core_1.NodeTypes.IF) {
// Check if v-else was followed by v-else-if
if (dir.name === 'else-if' &&
sibling.branches[sibling.branches.length - 1].vIf.condition === undefined) {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
}
// move the node to the if node's branches
context.removeNode();
sibling.branches.push(node);
const onExit = processCodegen &&
processCodegen(sibling, node, false);
// since the branch was removed, it will not be traversed.
// make sure to traverse here.
(0, transform_1.traverseNode)(node, context);
// call on exit
if (onExit)
onExit();
// make sure to reset currentNode after traversal to indicate this
// node has been removed.
context.currentNode = null;
}
else {
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
}
break;
}
}
}
exports.processIf = processIf;
function findVIfSpreadElement({ properties }) {
const len = properties.length;
for (let i = len - 1; i >= 0; i--) {
const prop = properties[i];
if ((0, types_1.isSpreadElement)(prop)) {
return prop;
}
}
}
function findVIfConditionalExpression(vIfConditionalExpression) {
if ((0, types_1.isConditionalExpression)(vIfConditionalExpression.alternate)) {
return findVIfConditionalExpression(vIfConditionalExpression.alternate);
}
return vIfConditionalExpression;
}
+2
View File
@@ -0,0 +1,2 @@
import { type DirectiveTransform } from '@vue/compiler-core';
export declare const transformModel: DirectiveTransform;
+210
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 === compiler_core_1.ElementTypes.COMPONENT) {
return transformComponentVModel(baseResult.props, node, context);
}
if (dir.arg) {
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT, dir.arg.loc));
}
function checkDuplicatedValue() {
const value = (0, compiler_core_1.findDir)(node, 'bind');
if (value && (0, compiler_core_1.isStaticArgOf)(value.arg, 'value')) {
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE, value.loc));
}
}
const { tag } = node;
if (tag === 'input' || tag === 'textarea') {
checkDuplicatedValue();
}
else {
context.onError((0, compiler_dom_1.createDOMCompilerError)(compiler_dom_1.DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT, dir.loc));
}
if (dir.modifiers.length) {
const arg = dir.arg;
const modifiers = dir.modifiers
.map((m) => ((0, compiler_core_1.isSimpleIdentifier)(m) ? m : JSON.stringify(m)) + `: true`)
.join(`, `);
const modifiersKey = arg
? (0, compiler_core_1.isStaticExp)(arg)
? `${arg.content}Modifiers`
: (0, compiler_core_1.createCompoundExpression)([arg, ' + "Modifiers"'])
: `modelModifiers`;
baseResult.props.push((0, compiler_core_1.createObjectProperty)(modifiersKey, (0, compiler_core_1.createSimpleExpression)(`{ ${modifiers} }`, false, dir.loc, compiler_core_1.ConstantTypes.CAN_HOIST)));
}
return transformElementVModel(baseResult.props, node, context);
};
exports.transformModel = transformModel;
function findInputDirectiveNode(props) {
return props.find((prop) => prop.type === compiler_core_1.NodeTypes.DIRECTIVE &&
prop.name === 'on' &&
prop.arg?.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
prop.arg.content === 'input');
}
function transformElementVModel(props, node, context) {
const dirs = transformVModel(props, node, context, {
isComponent: false,
binding: 'value',
event: 'input',
formatEventCode(code) {
return code.replace(/=\s\$event/g, `= $event.detail.value`);
},
});
if (dirs.length === 2) {
// 快手小程序的 input v-model 被转换到 data-e-o 中,补充到 data-e-o 中
const inputExp = findDatasetEventOpts(node);
if (inputExp) {
inputExp.children[2] = combineVOn(dirs[1].exp, inputExp.children[2], node, context);
dirs.length = 1;
}
else {
const inputDir = findInputDirectiveNode(node.props);
if (inputDir && inputDir.exp) {
// 合并到已有的 input 事件中
inputDir.exp = combineVOn(dirs[1].exp, inputDir.exp, node, context);
dirs.length = 1;
}
}
}
return { props: dirs };
}
/**
* {
* "type": 7,
* "name": "bind",
* "loc": {},
* "modifiers": [],
* "arg": {
* "type": 4,
* "loc": {},
* "content": "data-e-o",
* "isStatic": true,
* "constType": 3
* },
* "exp": {
* "type": 8,
* "loc": {},
* "children": ["{", {
* "type": 8,
* "loc": {},
* "children": ["'input'", ": ", {
* "type": 8,
* "loc": {},
* "children": ["_o(", {
* "type": 4,
* "content": "_ctx.input",
* "isStatic": false,
* "constType": 0,
* "loc": {}
* }, ")"]
* }, ","]
* }, "}"]
* }
* }
* @param node
* @returns
*/
function findDatasetEventOpts(node) {
const eventOptsProp = (0, compiler_core_1.findProp)(node, uni_cli_shared_1.ATTR_DATASET_EVENT_OPTS, true, false);
if (!eventOptsProp) {
return;
}
const { exp } = eventOptsProp;
if (exp?.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
return;
}
for (let i = 0; i < exp.children.length; i++) {
const childExp = exp.children[i];
if ((0, shared_1.isSymbol)(childExp) || (0, shared_1.isString)(childExp)) {
continue;
}
if (childExp.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
continue;
}
if (childExp.children[0] !== `'input'`) {
continue;
}
const inputExp = childExp.children[2];
if ((0, shared_1.isSymbol)(inputExp) ||
(0, shared_1.isString)(inputExp) ||
inputExp.type !== compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
continue;
}
return childExp;
}
}
function parseVOn(exp, context) {
return (0, codegen_1.genExpr)(exp).slice(context.helperString(runtimeHelpers_1.V_ON).length + 1, -1);
}
function combineVOn(exp1, exp2, node, context) {
return (0, vOn_1.wrapperVOn)((0, compiler_core_1.createCompoundExpression)([
`[`,
parseVOn(exp1, context),
',',
parseVOn(exp2, context),
`]`,
]), node, context);
}
function transformComponentVModel(props, node, context) {
return {
props: transformVModel(props, node, context, {
isComponent: true,
formatEventCode(code) {
return code;
},
}),
};
}
function transformVModel(props, node, context, { isComponent, binding, event, formatEventCode, }) {
if (props.length < 2) {
return [];
}
const { key: modelValueArg, value: modelValeExpr } = props[0];
const { key: onUpdateArg, value: onUpdateExpr } = props[1];
if (modelValueArg.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
return [];
}
if (onUpdateArg.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
!onUpdateArg.content.startsWith('onUpdate:')) {
return [];
}
const vBindModelValue = (0, uni_cli_shared_1.createBindDirectiveNode)(binding || modelValueArg.content, (0, codegen_1.genExpr)(modelValeExpr));
const modifiers = parseVModelModifiers(props[2]);
// onUpdateExpr 通常是 ExpressionNode 或者被 cache 的 ExpressionNode
const vOnValue = (onUpdateExpr.type === compiler_core_1.NodeTypes.JS_CACHE_EXPRESSION
? onUpdateExpr.value
: onUpdateExpr);
const vOnUpdate = (0, uni_cli_shared_1.createOnDirectiveNode)(event || (0, shared_1.camelize)(onUpdateArg.content.replace('onUpdate:', 'update-')), formatEventCode((0, codegen_1.genExpr)((0, vOn_1.wrapperVOn)(modifiers
? wrapperVModelModifiers(vOnValue, modifiers, context, isComponent)
: vOnValue, node, context))));
return [vBindModelValue, vOnUpdate];
}
function parseVModelModifiers(property) {
if (property &&
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.key) &&
property.key.content.endsWith('Modifiers') &&
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.value)) {
return property.value.content;
}
}
function wrapperVModelModifiers(exp, modifiers, context, isComponent = false) {
return (0, compiler_core_1.createCompoundExpression)([
`${context.helperString(runtimeHelpers_1.WITH_MODEL_MODIFIERS)}(`,
exp,
',',
modifiers,
`${isComponent ? `, true` : ``}`,
`)`,
]);
}
+8
View File
@@ -0,0 +1,8 @@
import { type DirectiveNode, type DirectiveTransform, type ElementNode, type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
import type { TransformContext } from '../transform';
export interface VOnDirectiveNode extends DirectiveNode {
arg: ExpressionNode;
exp: SimpleExpressionNode | undefined;
}
export declare const transformOn: DirectiveTransform;
export declare function wrapperVOn(value: ExpressionNode, node: ElementNode, context: TransformContext): ExpressionNode;
+172
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)(compiler_core_1.ErrorCodes.X_V_ON_NO_EXPRESSION, loc));
}
let eventName;
if (arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
if (arg.isStatic) {
const rawName = arg.content;
// for all event listeners, auto convert it to camelCase. See issue #2249
eventName = (0, compiler_core_1.createSimpleExpression)((0, shared_1.toHandlerKey)((0, shared_1.camelize)(rawName)), true, arg.loc);
}
else {
// #2388
eventName = (0, compiler_core_1.createCompoundExpression)([
// `${context.helperString(TO_HANDLER_KEY)}(`,
arg,
// `)`,
]);
}
}
else {
// already a compound expression.
eventName = arg;
eventName.children.unshift(`${context.helperString(compiler_core_1.TO_HANDLER_KEY)}(`);
eventName.children.push(`)`);
}
// handler processing
let exp = dir.exp;
if (exp && !exp.content.trim()) {
exp = undefined;
}
let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;
if (exp) {
const isMemberExp = (0, compiler_core_1.isMemberExpression)(exp.content, context);
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));
const hasMultipleStatements = exp.content.includes(`;`);
// process the expression since it's been skipped
if (context.prefixIdentifiers) {
isInlineStatement && context.addIdentifiers(`$event`);
exp = dir.exp = (0, transformExpression_1.processExpression)(exp, context, false, hasMultipleStatements);
isInlineStatement && context.removeIdentifiers(`$event`);
// with scope analysis, the function is hoistable if it has no reference
// to scope variables.
shouldCache =
context.cacheHandlers &&
// unnecessary to cache inside v-once
!context.inVOnce &&
// runtime constants don't need to be cached
// (this is analyzed by compileScript in SFC <script setup>)
!(exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&
// #1541 bail if this is a member exp handler passed to a component -
// we need to use the original function to preserve arity,
// e.g. <transition> relies on checking cb.length to determine
// transition end handling. Inline function is ok since its arity
// is preserved even when cached.
!(isMemberExp && node.tagType === compiler_core_1.ElementTypes.COMPONENT) &&
// bail if the function references closure variables (v-for, v-slot)
// it must be passed fresh to avoid stale values.
!(0, compiler_core_1.hasScopeRef)(exp, context.identifiers) &&
// wxs event
!isFilterExpr(exp, context);
// If the expression is optimizable and is a member expression pointing
// to a function, turn it into invocation (and wrap in an arrow function
// below) so that it always accesses the latest value when called - thus
// avoiding the need to be patched.
if (shouldCache && isMemberExp) {
if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
exp.content = `${exp.content} && ${exp.content}(...args)`;
}
else {
exp.children = [...exp.children, ` && `, ...exp.children, `(...args)`];
}
}
}
if (isInlineStatement || (shouldCache && isMemberExp)) {
// wrap inline statement in a function expression
exp = (0, compiler_core_1.createCompoundExpression)([
`${isInlineStatement
? context.isTS
? `($event: any)`
: `$event`
: `${context.isTS ? `\n//@ts-ignore\n` : ``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,
exp,
hasMultipleStatements ? `}` : `)`,
]);
}
}
let ret = {
props: [
(0, compiler_core_1.createObjectProperty)(eventName, exp || (0, compiler_core_1.createSimpleExpression)(`() => {}`, false, loc)),
],
};
// apply extended compiler augmentor
if (augmentor) {
ret = augmentor(ret);
}
// TODO
if (shouldCache) {
// cache handlers so that it's always the same handler being passed down.
// this avoids unnecessary re-renders when users use inline handlers on
// components.
// ret.props[0].value = wrapper(
// context.cache(ret.props[0].value) as ExpressionNode,
// context
// )
ret.props[0].value = wrapperVOn(ret.props[0].value, node, context);
}
else {
ret.props[0].value = wrapperVOn(ret.props[0].value, node, context);
}
// mark the key as handler for props normalization check
ret.props.forEach((p) => (p.key.isHandlerKey = true));
return ret;
};
exports.transformOn = transformOn;
function isFilterExpr(value, context) {
if (context.filters.length && value.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
const firstChild = value.children[0];
if (firstChild.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
context.filters.includes(firstChild.content)) {
return true;
}
}
return false;
}
function wrapperVOn(value, node, context) {
if ((0, transformExpression_1.isBuiltInIdentifier)(value)) {
return value;
}
// wxs event
if (isFilterExpr(value, context)) {
return value;
}
const keys = [];
if (context.miniProgram.event?.key && context.inVFor) {
let keyProp = (0, compiler_core_1.findProp)(node, 'key');
if (!keyProp) {
const vForScope = (0, vFor_1.parseVForScope)(context.currentScope);
if (vForScope) {
keyProp = (0, compiler_core_1.findProp)(vForScope.node, 'key');
}
}
// 对 for 中的所有事件增加 key 标记,避免微信小程序不更新事件对象
if (keyProp && (0, uni_cli_shared_1.isDirectiveNode)(keyProp) && keyProp.exp) {
const keyCode = (0, __1.genExpr)(keyProp.exp);
if (keyCode) {
keys.push(',');
keys.push((0, __1.genExpr)(keyProp.exp));
}
}
}
return (0, compiler_core_1.createCompoundExpression)([
`${context.helperString(runtimeHelpers_1.V_ON)}(`,
value,
...keys,
`)`,
]);
}
exports.wrapperVOn = wrapperVOn;
+16
View File
@@ -0,0 +1,16 @@
import { type BinaryExpression } from '@babel/types';
import { type ComponentNode, type CompoundExpressionNode, type DirectiveNode } from '@vue/compiler-core';
import type { CodegenScope, CodegenVForScope } from '../options';
import { type NodeTransform, type TransformContext } from '../transform';
export declare const transformSlot: NodeTransform;
export declare function rewriteVSlot(dir: DirectiveNode, context: TransformContext): void;
export declare function findSlotName(slotDir: DirectiveNode): string | CompoundExpressionNode;
export declare function findCurrentPath(id: string, scope: CodegenScope): BinaryExpression | import("@babel/types").StringLiteral;
/**
* 目前无用
* @param vForScope
* @param parentScope
* @param context
*/
export declare function rewriteScopedSlotVForScope(vForScope: CodegenVForScope, parentScope: CodegenScope, context: TransformContext): void;
export declare function createVSlotCallExpression(slotComponent: ComponentNode, vForScope: CodegenVForScope, context: TransformContext): import("@babel/types").CallExpression;
+274
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 !== compiler_core_1.NodeTypes.COMMENT) {
implicitDefaultChildren.push(slotElement);
}
continue;
}
if (onComponentSlot) {
// already has on-component slot - this is incorrect usage.
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc));
break;
}
if (!slotDir.arg) {
// v-slot => v-slot:default
slotDir.arg = (0, compiler_core_1.createSimpleExpression)('default', true);
}
const slotName = transformTemplateSlotElement(slotDir, slotElement, node, context);
// 小程序组件默认插槽,直接移除<template #default>节点
if (isMiniProgramComponent) {
if (slotName === 'default' && slotElement.children.length === 1) {
children.splice(i, 1, slotElement.children[0]);
}
continue;
}
if (slotName) {
slots.add(slotName);
}
}
if (isMiniProgramComponent) {
return;
}
if (implicitDefaultChildren.length) {
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
}
if (onComponentSlot) {
// <unicloud-db v-slot:default="{data, loading, error, options}"/>
// => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db>
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
const templateNode = createTemplateNode(onComponentSlot, implicitDefaultChildren);
transformTemplateSlotElement(onComponentSlot, templateNode, node, context);
node.children = [templateNode];
}
// 不支持 $slots, 则自动补充 props
if (slots.size && !context.miniProgram.slot.$slots) {
const slotsArr = [...slots];
const hasDynamic = slotsArr.find((name) => !(0, shared_1.isString)(name));
let value;
if (hasDynamic) {
const children = [];
const len = slotsArr.length - 1;
slotsArr.forEach((name, index) => {
if ((0, shared_1.isString)(name)) {
children.push(`'${(0, uni_shared_1.dynamicSlotName)(name)}'`);
}
else {
children.push(name);
}
if (index < len) {
children.push(',');
}
});
value = (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '([',
...children,
'])',
]);
}
else {
value = `[${slotsArr
.map((name) => `'${(0, uni_shared_1.dynamicSlotName)(name)}'`)
.join(',')}]`;
}
node.props.unshift((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_SLOTS, value));
}
};
exports.transformSlot = transformSlot;
function rewriteVSlot(dir, context) {
dir.arg = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '(',
dir.arg,
')',
]), context);
}
exports.rewriteVSlot = rewriteVSlot;
function transformTemplateSlotElement(slotDir, slotTemplate, slotComponent, context) {
const slotName = findSlotName(slotDir);
if (!slotName) {
return;
}
const { exp } = slotDir;
// non scoped slots
if (!exp) {
return slotName;
}
// empty
if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {
return slotName;
}
// 使用vFor来简单处理scoped slot作用域问题
slotTemplate.children = [
createVForTemplate(slotTemplate, { name: slotName, value: (0, codegen_1.genExpr)(exp), slotComponent }, context),
];
if (context.miniProgram.slot.dynamicSlotNames) {
// 已经在 vFor 中补充 slot,故需要移除 slotTemplate 中的
const index = slotTemplate.props.indexOf(slotDir);
if (index > -1) {
slotTemplate.props.splice(index, 1);
}
}
// v-slot="slotProps" => v-slot 避免 transformIdentifier 生成 slotProps 的变量声明
slotDir.exp = undefined;
return slotName;
}
function createTemplateNode(slotDir, children) {
return {
type: compiler_core_1.NodeTypes.ELEMENT,
tag: 'template',
tagType: compiler_core_1.ElementTypes.TEMPLATE,
loc: compiler_core_1.locStub,
isSelfClosing: false,
codegenNode: undefined,
ns: 0,
props: [slotDir],
children,
};
}
function findSlotName(slotDir) {
if (!slotDir.arg) {
return uni_shared_1.SLOT_DEFAULT_NAME;
}
if ((0, compiler_core_1.isStaticExp)(slotDir.arg)) {
return slotDir.arg.content;
}
return slotDir.arg;
}
exports.findSlotName = findSlotName;
function findCurrentVForValueAlias(context) {
let scope = context.currentScope;
while (scope) {
if ((0, transform_1.isVForScope)(scope)) {
return scope.valueAlias;
}
scope = scope.parent;
}
return '';
}
function createVForTemplate(slotElement, { name, value, slotComponent, }, context) {
const slotName = 's' + context.scopes.vFor;
const keyProp = (0, uni_cli_shared_1.createBindDirectiveNode)('key', 'i' + context.scopes.vFor);
const source = (0, shared_1.isString)(name) ? `'${name}'` : (0, codegen_1.genExpr)(name);
const vForProp = {
type: compiler_core_1.NodeTypes.DIRECTIVE,
name: 'for',
loc: compiler_core_1.locStub,
modifiers: [],
arg: undefined,
exp: (0, compiler_core_1.createSimpleExpression)(`(${value}, ${slotName}) in ${utils_1.SCOPED_SLOT_IDENTIFIER}(${source}, ${findCurrentVForValueAlias(context) || `''`})`),
};
const props = [vForProp, keyProp];
if (context.miniProgram.slot.dynamicSlotNames) {
props.push((0, uni_cli_shared_1.createBindDirectiveNode)('slot', slotName));
}
return {
loc: slotElement.loc,
ns: 0,
tag: 'template',
type: compiler_core_1.NodeTypes.ELEMENT,
tagType: compiler_core_1.ElementTypes.TEMPLATE,
props,
isSelfClosing: false,
codegenNode: undefined,
children: slotElement.children,
slotComponent,
};
}
const slotNameRE = /\('(.*)',/;
/**
* ('default','') => default
* @param source
* @returns
*/
function findCurrentSlotName(source) {
return (0, types_1.stringLiteral)((0, uni_shared_1.dynamicSlotName)(source.children[1].match(slotNameRE)[1]));
}
function createPathBinaryExpr(scope, computed = true) {
return (0, types_1.binaryExpression)('+', (0, types_1.binaryExpression)('+', (0, types_1.stringLiteral)(parseVForPath(scope.sourceAlias) + (computed ? '[' : '.')), (0, types_1.identifier)(scope.indexAlias)), (0, types_1.stringLiteral)(computed ? '].' : '.'));
}
function findCurrentPath(id, scope) {
let parent = scope.parent;
let binaryExpr = null;
while (parent) {
if ((0, transform_1.isVForScope)(parent)) {
// const computed = !isScopedSlotVFor(parent)
if (!binaryExpr) {
binaryExpr = createPathBinaryExpr(parent);
}
else {
binaryExpr = (0, types_1.binaryExpression)('+', createPathBinaryExpr(parent), binaryExpr);
}
}
parent = parent.parent;
}
return ((binaryExpr && (0, types_1.binaryExpression)('+', binaryExpr, (0, types_1.stringLiteral)(id))) ||
(0, types_1.stringLiteral)(id));
}
exports.findCurrentPath = findCurrentPath;
function findCurrentVueIdExpr(node, context) {
if (!node) {
return (0, types_1.stringLiteral)('');
}
const vueIdProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_ID);
if (vueIdProp.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
return (0, types_1.stringLiteral)(vueIdProp.value.content);
}
return (0, ast_1.parseExpr)((0, codegen_1.genExpr)(vueIdProp.exp), context) || (0, types_1.stringLiteral)('');
}
/**
* 目前无用
* @param vForScope
* @param parentScope
* @param context
*/
function rewriteScopedSlotVForScope(vForScope, parentScope, context) {
// 生成一个新的sourceAlias,用于scopedSlots
const { source, sourceExpr } = vForScope;
vForScope.sourceAlias = (0, utils_1.rewriteExpressionWithoutProperty)(source, context, sourceExpr, parentScope).content;
}
exports.rewriteScopedSlotVForScope = rewriteScopedSlotVForScope;
function parseVForPath(id) {
return id.includes('.') ? id.split('.')[1] : id;
}
function createVSlotCallExpression(slotComponent, vForScope, context) {
const { source, sourceAlias } = vForScope;
const id = parseVForPath(sourceAlias);
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.WITH_SCOPED_SLOT)), [
(0, vFor_1.createVForArrowFunctionExpression)(vForScope),
(0, types_1.objectExpression)([
// 插槽名称,数据更新 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;
+2
View File
@@ -0,0 +1,2 @@
import type { NodeTransform } from '../transform';
export declare const transformText: NodeTransform;
+28
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 !== compiler_core_1.ElementTypes.ELEMENT) {
return;
}
node.isSelfClosing = false;
node.children = [
{
type: compiler_core_1.NodeTypes.INTERPOLATION,
loc: dir.exp.loc,
content: dir.exp,
},
];
};
exports.transformText = transformText;
+1
View File
@@ -0,0 +1 @@
[https://dcloud.io/license/uni-app.html](https://dcloud.io/license/uni-app.html)
+36
View File
@@ -0,0 +1,36 @@
{
"name": "@dcloudio/uni-mp-compiler",
"version": "3.0.0-4030620241128001",
"description": "uni-mp-compiler",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
"directory": "packages/uni-mp-compiler"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "Apache-2.0",
"gitHead": "33e807d66e1fe47e2ee08ad9c59247e37b8884da",
"dependencies": {
"@babel/generator": "^7.20.5",
"@babel/parser": "^7.23.9",
"@babel/types": "^7.20.7",
"@dcloudio/uni-cli-shared": "3.0.0-4030620241128001",
"@dcloudio/uni-shared": "3.0.0-4030620241128001",
"@vue/compiler-core": "3.4.21",
"@vue/compiler-dom": "3.4.21",
"@vue/shared": "3.4.21",
"estree-walker": "^2.0.2"
},
"devDependencies": {
"@types/babel__generator": "^7.6.4",
"@vue/compiler-sfc": "3.4.21",
"source-map-js": "^1.0.2"
}
}