add scripts
This commit is contained in:
parent
1b53576b93
commit
f928e6eed3
|
@ -0,0 +1,69 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Adapters;
|
||||
(function (Adapters) {
|
||||
Adapters["weapp"] = "weapp";
|
||||
Adapters["swan"] = "swan";
|
||||
Adapters["alipay"] = "alipay";
|
||||
Adapters["quickapp"] = "quickapp";
|
||||
Adapters["tt"] = "tt";
|
||||
})(Adapters = exports.Adapters || (exports.Adapters = {}));
|
||||
const weixinAdapter = {
|
||||
if: 'wx:if',
|
||||
else: 'wx:else',
|
||||
elseif: 'wx:elif',
|
||||
for: 'wx:for',
|
||||
forItem: 'wx:for-item',
|
||||
forIndex: 'wx:for-index',
|
||||
key: 'wx:key',
|
||||
type: "weapp" /* weapp */
|
||||
};
|
||||
const swanAdapter = {
|
||||
if: 's-if',
|
||||
else: 's-else',
|
||||
elseif: 's-elif',
|
||||
for: 's-for',
|
||||
forItem: 's-for-item',
|
||||
forIndex: 's-for-index',
|
||||
key: 's-key',
|
||||
type: "swan" /* swan */
|
||||
};
|
||||
const alipayAdapter = {
|
||||
if: 'a:if',
|
||||
else: 'a:else',
|
||||
elseif: 'a:elif',
|
||||
for: 'a:for',
|
||||
forItem: 'a:for-item',
|
||||
forIndex: 'a:for-index',
|
||||
key: 'a:key',
|
||||
type: "alipay" /* alipay */
|
||||
};
|
||||
const ttAdapter = {
|
||||
if: 'tt:if',
|
||||
else: 'tt:else',
|
||||
elseif: 'tt:elif',
|
||||
for: 'tt:for',
|
||||
forItem: 'tt:for-item',
|
||||
forIndex: 'tt:for-index',
|
||||
key: 'tt:key',
|
||||
type: "tt" /* tt */
|
||||
};
|
||||
exports.Adapter = weixinAdapter;
|
||||
function setAdapter(adapter) {
|
||||
switch (adapter.toLowerCase()) {
|
||||
case "swan" /* swan */:
|
||||
exports.Adapter = swanAdapter;
|
||||
break;
|
||||
case "alipay" /* alipay */:
|
||||
exports.Adapter = alipayAdapter;
|
||||
break;
|
||||
case "tt" /* tt */:
|
||||
exports.Adapter = ttAdapter;
|
||||
break;
|
||||
default:
|
||||
exports.Adapter = weixinAdapter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
exports.setAdapter = setAdapter;
|
||||
//# sourceMappingURL=adapter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":";;AAAA,IAAkB,QAMjB;AAND,WAAkB,QAAQ;IACxB,2BAAe,CAAA;IACf,yBAAa,CAAA;IACb,6BAAiB,CAAA;IACjB,iCAAqB,CAAA;IACrB,qBAAS,CAAA;AACX,CAAC,EANiB,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAMzB;AAaD,MAAM,aAAa,GAAY;IAC7B,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,GAAG,EAAE,QAAQ;IACb,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,cAAc;IACxB,GAAG,EAAE,QAAQ;IACb,IAAI,qBAAgB;CACrB,CAAA;AAED,MAAM,WAAW,GAAY;IAC3B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,OAAO;IACZ,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,GAAG,EAAE,OAAO;IACZ,IAAI,mBAAe;CACpB,CAAA;AAED,MAAM,aAAa,GAAY;IAC7B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,OAAO;IACZ,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,GAAG,EAAE,OAAO;IACZ,IAAI,uBAAiB;CACtB,CAAA;AAED,MAAM,SAAS,GAAY;IACzB,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,GAAG,EAAE,QAAQ;IACb,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,cAAc;IACxB,GAAG,EAAE,QAAQ;IACb,IAAI,eAAa;CAClB,CAAA;AAEU,QAAA,OAAO,GAAY,aAAa,CAAA;AAE3C,SAAgB,UAAU,CAAE,OAAiB;IAC3C,QAAQ,OAAO,CAAC,WAAW,EAAE,EAAE;QAC7B;YACE,eAAO,GAAG,WAAW,CAAA;YACrB,MAAK;QACP;YACE,eAAO,GAAG,aAAa,CAAA;YACvB,MAAK;QACP;YACE,eAAO,GAAG,SAAS,CAAA;YACnB,MAAK;QACP;YACE,eAAO,GAAG,aAAa,CAAA;YACvB,MAAK;KACR;AACH,CAAC;AAfD,gCAeC"}
|
|
@ -0,0 +1,616 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const t = require("babel-types");
|
||||
const utils_1 = require("./utils");
|
||||
const constant_1 = require("./constant");
|
||||
const lodash_1 = require("lodash");
|
||||
const render_1 = require("./render");
|
||||
const jsx_1 = require("./jsx");
|
||||
const adapter_1 = require("./adapter");
|
||||
const babel_generator_1 = require("babel-generator");
|
||||
function buildConstructor() {
|
||||
const ctor = t.classMethod('constructor', t.identifier('constructor'), [t.identifier('props')], t.blockStatement([
|
||||
t.expressionStatement(t.callExpression(t.identifier('super'), [
|
||||
t.identifier('props')
|
||||
]))
|
||||
]));
|
||||
return ctor;
|
||||
}
|
||||
function processThisPropsFnMemberProperties(member, path, args, binded) {
|
||||
const propertyArray = [];
|
||||
function traverseMember(member) {
|
||||
const object = member.object;
|
||||
const property = member.property;
|
||||
if (t.isIdentifier(property)) {
|
||||
propertyArray.push(property.name);
|
||||
}
|
||||
if (t.isMemberExpression(object)) {
|
||||
if (t.isThisExpression(object.object) &&
|
||||
t.isIdentifier(object.property) &&
|
||||
object.property.name === 'props') {
|
||||
if ("alipay" /* alipay */ === adapter_1.Adapter.type) {
|
||||
if (binded)
|
||||
args.shift();
|
||||
path.replaceWith(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__triggerPropsFn')), [
|
||||
t.stringLiteral(propertyArray.reverse().join('.')),
|
||||
t.arrayExpression(args)
|
||||
]));
|
||||
}
|
||||
else {
|
||||
path.replaceWith(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__triggerPropsFn')), [t.stringLiteral(propertyArray.reverse().join('.')), t.callExpression(t.memberExpression(t.arrayExpression([t.nullLiteral()]), t.identifier('concat')), [t.arrayExpression(args)])]));
|
||||
}
|
||||
}
|
||||
traverseMember(object);
|
||||
}
|
||||
}
|
||||
traverseMember(member);
|
||||
}
|
||||
class Transformer {
|
||||
constructor(path, sourcePath, componentProperies) {
|
||||
this.result = {
|
||||
template: '',
|
||||
components: [],
|
||||
componentProperies: []
|
||||
};
|
||||
this.methods = new Map();
|
||||
this.initState = new Set();
|
||||
this.jsxReferencedIdentifiers = new Set();
|
||||
this.customComponents = new Map();
|
||||
this.anonymousMethod = new Map();
|
||||
this.renderMethod = null;
|
||||
this.customComponentNames = new Set();
|
||||
this.usedState = new Set();
|
||||
this.loopStateName = new Map();
|
||||
this.customComponentData = [];
|
||||
this.refs = [];
|
||||
this.loopRefs = new Map();
|
||||
this.anonymousFuncCounter = utils_1.incrementId();
|
||||
this.buildPropsAnonymousFunc = (attr, expr, isBind = false) => {
|
||||
const { code } = babel_generator_1.default(expr);
|
||||
if (code.startsWith('this.props')) {
|
||||
const methodName = utils_1.findMethodName(expr);
|
||||
const hasMethodName = this.anonymousMethod.has(methodName) || !methodName;
|
||||
const funcName = hasMethodName
|
||||
? this.anonymousMethod.get(methodName)
|
||||
// 测试时使用1个稳定的 uniqueID 便于测试,实际使用5个英文字母,否则小程序不支持
|
||||
: process.env.NODE_ENV === 'test' ? lodash_1.uniqueId('funPrivate') : `funPrivate${utils_1.createRandomLetters(5)}`;
|
||||
this.anonymousMethod.set(methodName, funcName);
|
||||
const newVal = isBind
|
||||
? t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(funcName)), t.identifier('bind')), expr.arguments || [])
|
||||
: t.memberExpression(t.thisExpression(), t.identifier(funcName));
|
||||
attr.get('value.expression').replaceWith(newVal);
|
||||
this.methods.set(funcName, null);
|
||||
this.componentProperies.add(methodName);
|
||||
if (hasMethodName) {
|
||||
return;
|
||||
}
|
||||
const attrName = attr.node.name;
|
||||
if (t.isJSXIdentifier(attrName) && attrName.name.startsWith('on')) {
|
||||
this.componentProperies.add(`__fn_${attrName.name}`);
|
||||
}
|
||||
if (methodName.startsWith('on')) {
|
||||
this.componentProperies.add(`__fn_${methodName}`);
|
||||
}
|
||||
const method = t.classMethod('method', t.identifier(funcName), [], t.blockStatement([
|
||||
t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__triggerPropsFn')), [t.stringLiteral(methodName), t.arrayExpression([t.spreadElement(t.identifier('arguments'))])]))
|
||||
]));
|
||||
this.classPath.node.body.body = this.classPath.node.body.body.concat(method);
|
||||
}
|
||||
};
|
||||
this.classPath = path;
|
||||
this.sourcePath = sourcePath;
|
||||
this.moduleNames = Object.keys(path.scope.getAllBindings('module'));
|
||||
this.componentProperies = new Set(componentProperies);
|
||||
this.compile();
|
||||
}
|
||||
setMultipleSlots() {
|
||||
const body = this.classPath.node.body.body;
|
||||
if (body.some(c => t.isClassProperty(c) && c.key.name === 'multipleSlots')) {
|
||||
return;
|
||||
}
|
||||
const multipleSlots = t.classProperty(t.identifier('multipleSlots'), t.booleanLiteral(true));
|
||||
multipleSlots.static = true;
|
||||
body.push(multipleSlots);
|
||||
}
|
||||
createStringRef(componentName, id, refName) {
|
||||
this.refs.push({
|
||||
type: constant_1.DEFAULT_Component_SET.has(componentName) ? 'dom' : 'component',
|
||||
id,
|
||||
refName
|
||||
});
|
||||
}
|
||||
createFunctionRef(componentName, id, fn) {
|
||||
this.refs.push({
|
||||
type: constant_1.DEFAULT_Component_SET.has(componentName) ? 'dom' : 'component',
|
||||
id,
|
||||
fn
|
||||
});
|
||||
}
|
||||
handleRefs() {
|
||||
const objExpr = this.refs.map(ref => {
|
||||
return t.objectExpression([
|
||||
t.objectProperty(t.identifier('type'), t.stringLiteral(ref.type)),
|
||||
t.objectProperty(t.identifier('id'), t.stringLiteral(ref.id)),
|
||||
t.objectProperty(t.identifier('refName'), t.stringLiteral(ref.refName || '')),
|
||||
t.objectProperty(t.identifier('fn'), ref.fn ? ref.fn : t.nullLiteral())
|
||||
]);
|
||||
});
|
||||
this.classPath.node.body.body.push(t.classProperty(t.identifier('$$refs'), t.arrayExpression(objExpr)));
|
||||
}
|
||||
traverse() {
|
||||
const self = this;
|
||||
self.classPath.traverse({
|
||||
JSXOpeningElement: (path) => {
|
||||
const jsx = path.node;
|
||||
const attrs = jsx.attributes;
|
||||
if (!t.isJSXIdentifier(jsx.name)) {
|
||||
return;
|
||||
}
|
||||
const loopCallExpr = path.findParent(p => utils_1.isArrayMapCallExpression(p));
|
||||
const componentName = jsx.name.name;
|
||||
const refAttr = jsx_1.findJSXAttrByName(attrs, 'ref');
|
||||
if (!refAttr) {
|
||||
return;
|
||||
}
|
||||
const idAttr = jsx_1.findJSXAttrByName(attrs, 'id');
|
||||
let id = utils_1.createRandomLetters(5);
|
||||
let idExpr;
|
||||
if (!idAttr) {
|
||||
if (loopCallExpr && loopCallExpr.isCallExpression()) {
|
||||
const [func] = loopCallExpr.node.arguments;
|
||||
let indexId = null;
|
||||
if (t.isFunctionExpression(func) || t.isArrowFunctionExpression(func)) {
|
||||
const params = func.params;
|
||||
indexId = params[1];
|
||||
}
|
||||
if (indexId === null || !t.isIdentifier(indexId)) {
|
||||
throw utils_1.codeFrameError(path.node, '在循环中使用 ref 必须暴露循环的第二个参数 `index`');
|
||||
}
|
||||
attrs.push(t.jSXAttribute(t.jSXIdentifier('id'), t.jSXExpressionContainer(t.binaryExpression('+', t.stringLiteral(id), indexId))));
|
||||
}
|
||||
else {
|
||||
attrs.push(t.jSXAttribute(t.jSXIdentifier('id'), t.stringLiteral(id)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const idValue = idAttr.value;
|
||||
if (t.isStringLiteral(idValue)) {
|
||||
id = idValue.value;
|
||||
}
|
||||
else if (t.isJSXExpressionContainer(idValue)) {
|
||||
if (t.isStringLiteral(idValue.expression)) {
|
||||
id = idValue.expression.value;
|
||||
}
|
||||
else {
|
||||
idExpr = idValue.expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t.isStringLiteral(refAttr.value)) {
|
||||
if (loopCallExpr) {
|
||||
throw utils_1.codeFrameError(refAttr, '循环中的 ref 只能使用函数。');
|
||||
}
|
||||
this.createStringRef(componentName, id, refAttr.value.value);
|
||||
}
|
||||
if (t.isJSXExpressionContainer(refAttr.value)) {
|
||||
const expr = refAttr.value.expression;
|
||||
if (t.isStringLiteral(expr)) {
|
||||
if (loopCallExpr) {
|
||||
throw utils_1.codeFrameError(refAttr, '循环中的 ref 只能使用函数。');
|
||||
}
|
||||
this.createStringRef(componentName, id, expr.value);
|
||||
}
|
||||
else if (t.isArrowFunctionExpression(expr) || t.isMemberExpression(expr)) {
|
||||
const type = constant_1.DEFAULT_Component_SET.has(componentName) ? 'dom' : 'component';
|
||||
if (loopCallExpr) {
|
||||
this.loopRefs.set(path.parentPath.node, {
|
||||
id: idExpr || id,
|
||||
fn: expr,
|
||||
type,
|
||||
component: path.parentPath
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.refs.push({
|
||||
type,
|
||||
id,
|
||||
fn: expr
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(refAttr, 'ref 仅支持传入字符串、匿名箭头函数和 class 中已声明的函数');
|
||||
}
|
||||
}
|
||||
for (const [index, attr] of attrs.entries()) {
|
||||
if (attr === refAttr) {
|
||||
attrs.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
ClassMethod(path) {
|
||||
const node = path.node;
|
||||
if (t.isIdentifier(node.key)) {
|
||||
const name = node.key.name;
|
||||
self.methods.set(name, path);
|
||||
if (name === 'render') {
|
||||
self.renderMethod = path;
|
||||
path.traverse({
|
||||
ReturnStatement(returnPath) {
|
||||
const arg = returnPath.node.argument;
|
||||
const ifStem = returnPath.findParent(p => p.isIfStatement());
|
||||
if (ifStem && ifStem.isIfStatement() && arg === null) {
|
||||
const consequent = ifStem.get('consequent');
|
||||
if (consequent.isBlockStatement() && consequent.node.body.includes(returnPath.node)) {
|
||||
returnPath.get('argument').replaceWith(t.nullLiteral());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (name === 'constructor') {
|
||||
path.traverse({
|
||||
AssignmentExpression(p) {
|
||||
if (t.isMemberExpression(p.node.left) &&
|
||||
t.isThisExpression(p.node.left.object) &&
|
||||
t.isIdentifier(p.node.left.property) &&
|
||||
p.node.left.property.name === 'state' &&
|
||||
t.isObjectExpression(p.node.right)) {
|
||||
const properties = p.node.right.properties;
|
||||
properties.forEach(p => {
|
||||
if (t.isObjectProperty(p) && t.isIdentifier(p.key)) {
|
||||
self.initState.add(p.key.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
IfStatement(path) {
|
||||
const test = path.get('test');
|
||||
const consequent = path.get('consequent');
|
||||
if (utils_1.isContainJSXElement(consequent) && utils_1.hasComplexExpression(test)) {
|
||||
const scope = self.renderMethod && self.renderMethod.scope || path.scope;
|
||||
utils_1.generateAnonymousState(scope, test, self.jsxReferencedIdentifiers, true);
|
||||
}
|
||||
},
|
||||
ClassProperty(path) {
|
||||
const { key: { name }, value } = path.node;
|
||||
if (t.isArrowFunctionExpression(value) || t.isFunctionExpression(value)) {
|
||||
self.methods.set(name, path);
|
||||
}
|
||||
if (name === 'state' && t.isObjectExpression(value)) {
|
||||
value.properties.forEach(p => {
|
||||
if (t.isObjectProperty(p)) {
|
||||
if (t.isIdentifier(p.key)) {
|
||||
self.initState.add(p.key.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
JSXExpressionContainer(path) {
|
||||
const attr = path.findParent(p => p.isJSXAttribute());
|
||||
const isFunctionProp = attr && typeof attr.node.name.name === 'string' && attr.node.name.name.startsWith('on');
|
||||
path.traverse({
|
||||
MemberExpression(path) {
|
||||
const sibling = path.getSibling('property');
|
||||
if (path.get('object').isThisExpression() &&
|
||||
(path.get('property').isIdentifier({ name: 'props' }) || path.get('property').isIdentifier({ name: 'state' })) &&
|
||||
sibling.isIdentifier()) {
|
||||
if (!isFunctionProp) {
|
||||
self.usedState.add(sibling.node.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const expression = path.get('expression');
|
||||
const scope = self.renderMethod && self.renderMethod.scope || path.scope;
|
||||
const calleeExpr = expression.get('callee');
|
||||
const parentPath = path.parentPath;
|
||||
if (utils_1.hasComplexExpression(expression) &&
|
||||
!isFunctionProp &&
|
||||
!(calleeExpr &&
|
||||
calleeExpr.isMemberExpression() &&
|
||||
calleeExpr.get('object').isMemberExpression() &&
|
||||
calleeExpr.get('property').isIdentifier({ name: 'bind' })) // is not bind
|
||||
) {
|
||||
utils_1.generateAnonymousState(scope, expression, self.jsxReferencedIdentifiers);
|
||||
}
|
||||
else {
|
||||
if (parentPath.isJSXAttribute()) {
|
||||
if (!(expression.isMemberExpression() || expression.isIdentifier()) && parentPath.node.name.name === 'key') {
|
||||
utils_1.generateAnonymousState(scope, expression, self.jsxReferencedIdentifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!attr)
|
||||
return;
|
||||
const key = attr.node.name;
|
||||
const value = attr.node.value;
|
||||
if (!t.isJSXIdentifier(key)) {
|
||||
return;
|
||||
}
|
||||
if (t.isJSXIdentifier(key) && key.name.startsWith('on') && t.isJSXExpressionContainer(value)) {
|
||||
const expr = value.expression;
|
||||
if (t.isCallExpression(expr) && t.isMemberExpression(expr.callee) && t.isIdentifier(expr.callee.property, { name: 'bind' })) {
|
||||
self.buildPropsAnonymousFunc(attr, expr, true);
|
||||
}
|
||||
else if (t.isMemberExpression(expr)) {
|
||||
self.buildPropsAnonymousFunc(attr, expr, false);
|
||||
}
|
||||
else if (t.isArrowFunctionExpression(expr)) {
|
||||
const exprPath = attr.get('value.expression');
|
||||
const stemParent = path.getStatementParent();
|
||||
const counter = self.anonymousFuncCounter();
|
||||
const anonymousFuncName = `anonymousFunc${counter}`;
|
||||
const isCatch = utils_1.isContainStopPropagation(exprPath);
|
||||
const classBody = self.classPath.node.body.body;
|
||||
const loopCallExpr = path.findParent(p => utils_1.isArrayMapCallExpression(p));
|
||||
let index;
|
||||
if (loopCallExpr) {
|
||||
index = lodash_1.get(loopCallExpr, 'node.arguments[0].params[1]');
|
||||
if (!t.isIdentifier(index)) {
|
||||
index = t.identifier('__index' + counter);
|
||||
lodash_1.set(loopCallExpr, 'node.arguments[0].params[1]', index);
|
||||
}
|
||||
classBody.push(t.classProperty(t.identifier(anonymousFuncName + 'Array'), t.arrayExpression([])));
|
||||
const arrayFunc = t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName + 'Array')), t.identifier(index.name), true);
|
||||
classBody.push(t.classMethod('method', t.identifier(anonymousFuncName), [t.identifier(index.name), t.identifier('e')], t.blockStatement([
|
||||
isCatch ? t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('e'), t.identifier('stopPropagation')), [])) : t.emptyStatement(),
|
||||
t.expressionStatement(t.logicalExpression('&&', arrayFunc, t.callExpression(arrayFunc, [t.identifier('e')])))
|
||||
])));
|
||||
exprPath.replaceWith(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName)), t.identifier('bind')), [t.thisExpression(), t.identifier(index.name)]));
|
||||
stemParent.insertBefore(t.expressionStatement(t.assignmentExpression('=', arrayFunc, expr)));
|
||||
}
|
||||
else {
|
||||
classBody.push(t.classMethod('method', t.identifier(anonymousFuncName), [t.identifier('e')], t.blockStatement([
|
||||
isCatch ? t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('e'), t.identifier('stopPropagation')), [])) : t.emptyStatement()
|
||||
])));
|
||||
exprPath.replaceWith(t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName)));
|
||||
stemParent.insertBefore(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName)), expr)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(path.node, '组件事件传参只能在使用匿名箭头函数,或使用类作用域下的确切引用(this.handleXX || this.props.handleXX),或使用 bind。');
|
||||
}
|
||||
}
|
||||
const jsx = path.findParent(p => p.isJSXOpeningElement());
|
||||
if (!jsx)
|
||||
return;
|
||||
const jsxName = jsx.node.name;
|
||||
if (!t.isJSXIdentifier(jsxName))
|
||||
return;
|
||||
if (expression.isJSXElement())
|
||||
return;
|
||||
if (constant_1.DEFAULT_Component_SET.has(jsxName.name) || expression.isIdentifier() || expression.isMemberExpression() || expression.isLiteral() || expression.isLogicalExpression() || expression.isConditionalExpression() || key.name.startsWith('on') || expression.isCallExpression())
|
||||
return;
|
||||
utils_1.generateAnonymousState(scope, expression, self.jsxReferencedIdentifiers);
|
||||
},
|
||||
JSXElement(path) {
|
||||
const id = path.node.openingElement.name;
|
||||
if (t.isJSXIdentifier(id) &&
|
||||
!constant_1.DEFAULT_Component_SET.has(id.name) &&
|
||||
self.moduleNames.indexOf(id.name) !== -1) {
|
||||
const name = id.name;
|
||||
const binding = self.classPath.scope.getBinding(name);
|
||||
if (binding && t.isImportDeclaration(binding.path.parent)) {
|
||||
const sourcePath = binding.path.parent.source.value;
|
||||
if (binding.path.isImportDefaultSpecifier()) {
|
||||
self.customComponents.set(name, {
|
||||
sourcePath,
|
||||
type: 'default'
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.customComponents.set(name, {
|
||||
sourcePath,
|
||||
type: 'pattern'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
MemberExpression: (path) => {
|
||||
const object = path.get('object');
|
||||
const property = path.get('property');
|
||||
if (!(object.isThisExpression() && property.isIdentifier({ name: 'props' }))) {
|
||||
return;
|
||||
}
|
||||
const parentPath = path.parentPath;
|
||||
if (parentPath.isMemberExpression()) {
|
||||
const siblingProp = parentPath.get('property');
|
||||
if (siblingProp.isIdentifier()) {
|
||||
const name = siblingProp.node.name;
|
||||
if (name === 'children') {
|
||||
parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [], true));
|
||||
}
|
||||
else if (/^render[A-Z]/.test(name)) {
|
||||
const slotName = utils_1.getSlotName(name);
|
||||
parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [
|
||||
t.jSXAttribute(t.jSXIdentifier('name'), t.stringLiteral(slotName))
|
||||
], true), t.jSXClosingElement(t.jSXIdentifier('slot')), []));
|
||||
this.setMultipleSlots();
|
||||
}
|
||||
else {
|
||||
self.componentProperies.add(siblingProp.node.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parentPath.isVariableDeclarator()) {
|
||||
const siblingId = parentPath.get('id');
|
||||
if (siblingId.isObjectPattern()) {
|
||||
const properties = siblingId.node.properties;
|
||||
for (const prop of properties) {
|
||||
if (t.isRestProperty(prop)) {
|
||||
throw utils_1.codeFrameError(prop.loc, 'this.props 不支持使用 rest property 语法,请把每一个 prop 都单独列出来');
|
||||
}
|
||||
else if (t.isIdentifier(prop.key)) {
|
||||
self.componentProperies.add(prop.key.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
CallExpression(path) {
|
||||
const node = path.node;
|
||||
const callee = node.callee;
|
||||
if (t.isMemberExpression(callee) && t.isMemberExpression(callee.object)) {
|
||||
const property = callee.property;
|
||||
if (t.isIdentifier(property)) {
|
||||
if (property.name.startsWith('on')) {
|
||||
self.componentProperies.add(`__fn_${property.name}`);
|
||||
processThisPropsFnMemberProperties(callee, path, node.arguments, false);
|
||||
}
|
||||
else if (property.name === 'call' || property.name === 'apply') {
|
||||
self.componentProperies.add(`__fn_${property.name}`);
|
||||
processThisPropsFnMemberProperties(callee.object, path, node.arguments, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
setComponents() {
|
||||
this.customComponents.forEach((component, name) => {
|
||||
this.result.components.push({
|
||||
path: utils_1.pathResolver(component.sourcePath, this.sourcePath),
|
||||
name: lodash_1.kebabCase(name),
|
||||
type: component.type
|
||||
});
|
||||
});
|
||||
}
|
||||
setMethods() {
|
||||
const methods = this.classPath.get('body').get('body');
|
||||
for (const method of methods) {
|
||||
if (method.isClassMethod()) {
|
||||
const key = method.get('key');
|
||||
if (key.isIdentifier()) {
|
||||
this.methods.set(key.node.name, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resetConstructor() {
|
||||
const body = this.classPath.node.body.body;
|
||||
if (!this.methods.has('constructor')) {
|
||||
const ctor = buildConstructor();
|
||||
body.unshift(ctor);
|
||||
}
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
return;
|
||||
}
|
||||
for (const method of body) {
|
||||
if (t.isClassMethod(method) && method.kind === 'constructor') {
|
||||
method.kind = 'method';
|
||||
method.key = t.identifier('_constructor');
|
||||
if (t.isBlockStatement(method.body)) {
|
||||
for (const statement of method.body.body) {
|
||||
if (t.isExpressionStatement(statement)) {
|
||||
const expr = statement.expression;
|
||||
if (t.isCallExpression(expr) && (t.isIdentifier(expr.callee, { name: 'super' }) || t.isSuper(expr.callee))) {
|
||||
expr.callee = t.memberExpression(t.identifier('super'), t.identifier('_constructor'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handleLifecyclePropParam(propParam, properties) {
|
||||
let propsName = null;
|
||||
if (!propParam) {
|
||||
return null;
|
||||
}
|
||||
if (t.isIdentifier(propParam)) {
|
||||
propsName = propParam.name;
|
||||
}
|
||||
else if (t.isObjectPattern(propParam)) {
|
||||
for (const prop of propParam.properties) {
|
||||
if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
|
||||
properties.add(prop.key.name);
|
||||
}
|
||||
else if (t.isRestProperty(prop) && t.isIdentifier(prop.argument)) {
|
||||
propsName = prop.argument.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(propParam.loc, '此生命周期的第一个参数只支持写标识符或对象解构');
|
||||
}
|
||||
return propsName;
|
||||
}
|
||||
findMoreProps() {
|
||||
// 第一个参数是 props 的生命周期
|
||||
const lifeCycles = new Set([
|
||||
// 'constructor',
|
||||
'componentDidUpdate',
|
||||
'shouldComponentUpdate',
|
||||
'getDerivedStateFromProps',
|
||||
'getSnapshotBeforeUpdate',
|
||||
'componentWillReceiveProps',
|
||||
'componentWillUpdate'
|
||||
]);
|
||||
const properties = new Set();
|
||||
this.methods.forEach((method, name) => {
|
||||
if (!lifeCycles.has(name)) {
|
||||
return;
|
||||
}
|
||||
const node = method.node;
|
||||
let propsName = null;
|
||||
if (t.isClassMethod(node)) {
|
||||
propsName = this.handleLifecyclePropParam(node.params[0], properties);
|
||||
}
|
||||
else if (t.isArrowFunctionExpression(node.value) || t.isFunctionExpression(node.value)) {
|
||||
propsName = this.handleLifecyclePropParam(node.value.params[0], properties);
|
||||
}
|
||||
if (propsName === null) {
|
||||
return;
|
||||
}
|
||||
method.traverse({
|
||||
MemberExpression(path) {
|
||||
if (!path.isReferencedMemberExpression()) {
|
||||
return;
|
||||
}
|
||||
const { object, property } = path.node;
|
||||
if (t.isIdentifier(object, { name: propsName }) && t.isIdentifier(property)) {
|
||||
properties.add(property.name);
|
||||
}
|
||||
},
|
||||
VariableDeclarator(path) {
|
||||
const { id, init } = path.node;
|
||||
if (t.isObjectPattern(id) && t.isIdentifier(init, { name: propsName })) {
|
||||
for (const prop of id.properties) {
|
||||
if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
|
||||
properties.add(prop.key.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
properties.forEach((value) => {
|
||||
this.componentProperies.add(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
parseRender() {
|
||||
if (this.renderMethod) {
|
||||
this.result.template = this.result.template
|
||||
+ new render_1.RenderParser(this.renderMethod, this.methods, this.initState, this.jsxReferencedIdentifiers, this.usedState, this.loopStateName, this.customComponentNames, this.customComponentData, this.componentProperies, this.loopRefs).outputTemplate;
|
||||
}
|
||||
}
|
||||
compile() {
|
||||
this.traverse();
|
||||
this.setMethods();
|
||||
this.setComponents();
|
||||
this.resetConstructor();
|
||||
this.findMoreProps();
|
||||
this.handleRefs();
|
||||
this.parseRender();
|
||||
this.result.componentProperies = [...this.componentProperies];
|
||||
}
|
||||
}
|
||||
exports.Transformer = Transformer;
|
||||
//# sourceMappingURL=class.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,94 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.THIRD_PARTY_COMPONENTS = new Set();
|
||||
// tslint:disable-next-line:variable-name
|
||||
exports.DEFAULT_Component_SET = new Set([
|
||||
'view',
|
||||
'scroll-view',
|
||||
'swiper',
|
||||
'movable-view',
|
||||
'cover-view',
|
||||
'cover-image',
|
||||
'icon',
|
||||
'text',
|
||||
'rich-text',
|
||||
'progress',
|
||||
'button',
|
||||
'checkbox',
|
||||
'form',
|
||||
'input',
|
||||
'label',
|
||||
'picker',
|
||||
'picker-view',
|
||||
'picker-view-column',
|
||||
'radio',
|
||||
'radio-group',
|
||||
'checkbox-group',
|
||||
'slider',
|
||||
'switch',
|
||||
'textarea',
|
||||
'navigator',
|
||||
'audio',
|
||||
'image',
|
||||
'video',
|
||||
'camera',
|
||||
'live-player',
|
||||
'live-pusher',
|
||||
'map',
|
||||
'canvas',
|
||||
'open-data',
|
||||
'web-view',
|
||||
'swiper-item',
|
||||
'movable-area',
|
||||
'movable-view',
|
||||
'functional-page-navigator',
|
||||
'ad',
|
||||
'block',
|
||||
'import',
|
||||
'official-account'
|
||||
]);
|
||||
exports.INTERNAL_SAFE_GET = 'internal_safe_get';
|
||||
exports.TARO_PACKAGE_NAME = '@tarojs/taro';
|
||||
exports.COMPONENTS_PACKAGE_NAME = '@tarojs/components';
|
||||
exports.REDUX_PACKAGE_NAME = '@tarojs/redux';
|
||||
exports.MOBX_PACKAGE_NAME = '@tarojs/mobx';
|
||||
exports.MAP_CALL_ITERATOR = '__item';
|
||||
exports.INTERNAL_INLINE_STYLE = 'internal_inline_style';
|
||||
exports.INTERNAL_GET_ORIGNAL = 'internal_get_original';
|
||||
exports.GEL_ELEMENT_BY_ID = 'getElementById';
|
||||
exports.LOOP_STATE = '$loopState';
|
||||
exports.LOOP_ORIGINAL = '$original';
|
||||
exports.setLoopOriginal = (s) => exports.LOOP_ORIGINAL = s;
|
||||
exports.LOOP_CALLEE = '$anonymousCallee_';
|
||||
exports.SPECIAL_COMPONENT_PROPS = new Map();
|
||||
exports.SPECIAL_COMPONENT_PROPS.set('Progress', new Set([
|
||||
'activeColor',
|
||||
'backgroundColor'
|
||||
]));
|
||||
exports.IMAGE_COMPONENTS = new Set([
|
||||
'Image',
|
||||
'CoverImage'
|
||||
]);
|
||||
exports.swanSpecialAttrs = {
|
||||
'ScrollView': ['scrollTop', 'scrollLeft', 'scrollIntoView'],
|
||||
'Input': ['value'],
|
||||
'Textarea': ['value'],
|
||||
'MovableView': ['x', 'y'],
|
||||
'Slider': ['value']
|
||||
};
|
||||
exports.ALIPAY_BUBBLE_EVENTS = new Set([
|
||||
'onTouchStart',
|
||||
'onTouchMove',
|
||||
'onTouchEnd',
|
||||
'onTouchCancel',
|
||||
'onClick',
|
||||
'onLongTap'
|
||||
]);
|
||||
exports.TRANSFORM_COMPONENT_PROPS = new Map();
|
||||
exports.TRANSFORM_COMPONENT_PROPS.set("alipay" /* alipay */, {
|
||||
'Canvas': {
|
||||
'canvasId': 'id'
|
||||
}
|
||||
});
|
||||
exports.lessThanSignPlacehold = '__LESS_THAN_SIGN_PLACEHOLDER__';
|
||||
//# sourceMappingURL=constant.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"constant.js","sourceRoot":"","sources":["../../src/constant.ts"],"names":[],"mappings":";;AAEa,QAAA,sBAAsB,GAAG,IAAI,GAAG,EAAU,CAAA;AAEvD,yCAAyC;AAC5B,QAAA,qBAAqB,GAAG,IAAI,GAAG,CAAS;IACnD,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,aAAa;IACb,WAAW;IACX,YAAY;IACZ,MAAM;IACN,MAAM;IACN,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,kBAAkB;IAClB,OAAO;IACP,YAAY;IACZ,eAAe;IACf,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,WAAW;IACX,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,YAAY;IACZ,KAAK;IACL,QAAQ;IACR,UAAU;IACV,SAAS;IACT,YAAY;IACZ,aAAa;IACb,aAAa;IACb,yBAAyB;IACzB,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,iBAAiB;CAClB,CAAC,CAAA;AAEW,QAAA,iBAAiB,GAAG,mBAAmB,CAAA;AAEvC,QAAA,iBAAiB,GAAG,cAAc,CAAA;AAElC,QAAA,uBAAuB,GAAG,oBAAoB,CAAA;AAE9C,QAAA,kBAAkB,GAAG,eAAe,CAAA;AAEpC,QAAA,iBAAiB,GAAG,cAAc,CAAA;AAElC,QAAA,iBAAiB,GAAG,QAAQ,CAAA;AAE5B,QAAA,qBAAqB,GAAG,uBAAuB,CAAA;AAE/C,QAAA,oBAAoB,GAAG,uBAAuB,CAAA;AAE9C,QAAA,iBAAiB,GAAG,gBAAgB,CAAA;AAEpC,QAAA,UAAU,GAAG,YAAY,CAAA;AAE3B,QAAA,aAAa,GAAG,WAAW,CAAA;AAEzB,QAAA,eAAe,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,qBAAa,GAAG,CAAC,CAAA;AAElD,QAAA,WAAW,GAAG,mBAAmB,CAAA;AAEjC,QAAA,uBAAuB,GAAG,IAAI,GAAG,EAAuB,CAAA;AAErE,+BAAuB,CAAC,GAAG,CACzB,UAAU,EACV,IAAI,GAAG,CAAC;IACN,aAAa;IACb,iBAAiB;CAClB,CAAC,CACH,CAAA;AAEY,QAAA,gBAAgB,GAAG,IAAI,GAAG,CAAS;IAC9C,OAAO;IACP,YAAY;CACb,CAAC,CAAA;AAEW,QAAA,gBAAgB,GAAG;IAC9B,YAAY,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,gBAAgB,CAAC;IAC3D,OAAO,EAAE,CAAC,OAAO,CAAC;IAClB,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;IACzB,QAAQ,EAAE,CAAC,OAAO,CAAC;CACpB,CAAA;AAEY,QAAA,oBAAoB,GAAG,IAAI,GAAG,CAAS;IAClD,cAAc;IACd,aAAa;IACb,YAAY;IACZ,eAAe;IACf,SAAS;IACT,WAAW;CACZ,CAAC,CAAA;AAEW,QAAA,yBAAyB,GAAG,IAAI,GAAG,EAA0D,CAAA;AAE1G,iCAAyB,CAAC,GAAG,wBAAkB;IAC7C,QAAQ,EAAE;QACR,UAAU,EAAE,IAAI;KACjB;CACF,CAAC,CAAA;AAEW,QAAA,qBAAqB,GAAG,gCAAgC,CAAA"}
|
|
@ -0,0 +1,43 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const voidHtmlTags = new Set([
|
||||
// 'image',
|
||||
'img',
|
||||
'input',
|
||||
'import'
|
||||
]);
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
voidHtmlTags.add('image');
|
||||
}
|
||||
function stringifyAttributes(input) {
|
||||
const attributes = [];
|
||||
for (const key of Object.keys(input)) {
|
||||
let value = input[key];
|
||||
if (value === false) {
|
||||
continue;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
value = value.join(' ');
|
||||
}
|
||||
let attribute = key;
|
||||
if (value !== true) {
|
||||
attribute += `="${String(value)}"`;
|
||||
}
|
||||
attributes.push(attribute);
|
||||
}
|
||||
return attributes.length > 0 ? ' ' + attributes.join(' ') : '';
|
||||
}
|
||||
exports.createHTMLElement = (options) => {
|
||||
options = Object.assign({
|
||||
name: 'div',
|
||||
attributes: {},
|
||||
value: ''
|
||||
}, options);
|
||||
const isVoidTag = voidHtmlTags.has(options.name);
|
||||
let ret = `<${options.name}${stringifyAttributes(options.attributes)}${isVoidTag ? `/` : ''}>`;
|
||||
if (!isVoidTag) {
|
||||
ret += `${options.value}</${options.name}>`;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
//# sourceMappingURL=create-html-element.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"create-html-element.js","sourceRoot":"","sources":["../../src/create-html-element.ts"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS;IACnC,WAAW;IACX,KAAK;IACL,OAAO;IACP,QAAQ;CACT,CAAC,CAAA;AAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE;IACnC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;CAC1B;AAQD,SAAS,mBAAmB,CAAE,KAAa;IACzC,MAAM,UAAU,GAAa,EAAE,CAAA;IAE/B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACpC,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;QAEtB,IAAI,KAAK,KAAK,KAAK,EAAE;YACnB,SAAQ;SACT;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACxB,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;SACxB;QAED,IAAI,SAAS,GAAG,GAAG,CAAA;QAEnB,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,SAAS,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,CAAA;SACnC;QAED,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;KAC3B;IAED,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AAEhE,CAAC;AAEY,QAAA,iBAAiB,GAAG,CAAC,OAAgB,EAAE,EAAE;IACpD,OAAO,GAAG,MAAM,CAAC,MAAM,CACrB;QACE,IAAI,EAAE,KAAK;QACX,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,EAAE;KACV,EACD,OAAO,CACR,CAAA;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAEhD,IAAI,GAAG,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAG,GAAG,CAAA;IAE/F,IAAI,CAAC,SAAS,EAAE;QACd,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,GAAG,CAAA;KAC5C;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA"}
|
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const eslint_1 = require("eslint");
|
||||
const utils_1 = require("./utils");
|
||||
const cli = new eslint_1.CLIEngine({
|
||||
baseConfig: {
|
||||
extends: ['plugin:taro/transformer']
|
||||
},
|
||||
useEslintrc: false,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
legacyDecorators: true
|
||||
}
|
||||
}
|
||||
});
|
||||
exports.eslintValidation = () => {
|
||||
return {
|
||||
visitor: {
|
||||
Program(_, state) {
|
||||
const { file: { code } } = state;
|
||||
const report = cli.executeOnText(code);
|
||||
if (report.errorCount > 0) {
|
||||
for (const result of report.results) {
|
||||
for (const msg of result.messages) {
|
||||
const err = utils_1.codeFrameError({
|
||||
start: {
|
||||
line: msg.line,
|
||||
column: msg.column
|
||||
},
|
||||
end: {
|
||||
line: msg.endLine,
|
||||
column: msg.endColumn
|
||||
}
|
||||
}, msg.message);
|
||||
// tslint:disable-next-line
|
||||
console.warn('\n' + `ESLint(${msg.ruleId}) 错误:` + err.message + '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=eslint.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"eslint.js","sourceRoot":"","sources":["../../src/eslint.ts"],"names":[],"mappings":";;AAAA,mCAAkC;AAElC,mCAAwC;AAExC,MAAM,GAAG,GAAG,IAAI,kBAAS,CAAC;IACxB,UAAU,EAAE;QACV,OAAO,EAAE,CAAC,yBAAyB,CAAC;KACrC;IACD,WAAW,EAAE,KAAK;IAClB,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE;QACb,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE;YACZ,GAAG,EAAE,IAAI;YACT,gBAAgB,EAAE,IAAI;SACvB;KACF;CACF,CAAC,CAAA;AAEW,QAAA,gBAAgB,GAEzB,GAAG,EAAE;IACP,OAAO;QACL,OAAO,EAAE;YACP,OAAO,CAAE,CAAC,EAAE,KAAK;gBACf,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,KAAK,CAAA;gBAChC,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;gBACtC,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE;oBACzB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE;wBACnC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE;4BACjC,MAAM,GAAG,GAAG,sBAAc,CAAC;gCACzB,KAAK,EAAE;oCACL,IAAI,EAAE,GAAG,CAAC,IAAI;oCACd,MAAM,EAAE,GAAG,CAAC,MAAM;iCACnB;gCACD,GAAG,EAAE;oCACH,IAAI,EAAE,GAAG,CAAC,OAAO;oCACjB,MAAM,EAAE,GAAG,CAAC,SAAS;iCACtB;6BACF,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;4BACf,2BAA2B;4BAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,UAAU,GAAG,CAAC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;yBACtE;qBACF;iBACF;YACH,CAAC;SACF;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@ -0,0 +1,83 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("./utils");
|
||||
const t = require("babel-types");
|
||||
const lodash_1 = require("lodash");
|
||||
function initialIsCapital(word) {
|
||||
return word[0] !== word[0].toLowerCase();
|
||||
}
|
||||
exports.functionalComponent = () => {
|
||||
return {
|
||||
visitor: {
|
||||
JSXElement(path) {
|
||||
const arrowFuncExpr = path.findParent(p => p.isArrowFunctionExpression());
|
||||
if (arrowFuncExpr && arrowFuncExpr.isArrowFunctionExpression() && arrowFuncExpr.parentPath.isVariableDeclarator()) {
|
||||
const valDecl = arrowFuncExpr.parentPath.parentPath;
|
||||
if (!valDecl.isVariableDeclaration()) {
|
||||
throw utils_1.codeFrameError(valDecl.node, '函数式组件不能同时定义多个值');
|
||||
}
|
||||
const id = arrowFuncExpr.parentPath.node.id;
|
||||
if (!t.isIdentifier(id)) {
|
||||
throw utils_1.codeFrameError(id, '函数式组件只能使用普通标识符定义');
|
||||
}
|
||||
if (!initialIsCapital(id.name)) {
|
||||
throw utils_1.codeFrameError(id, '组件命名规则请遵守帕斯卡命名法(Pascal Case)');
|
||||
}
|
||||
const hasClassDecl = arrowFuncExpr.findParent(p => p.isClassDeclaration());
|
||||
if (hasClassDecl) {
|
||||
// @TODO: 加上链接
|
||||
throw utils_1.codeFrameError(arrowFuncExpr.node, '在类中的函数式组件请写成类函数式组件:参考:');
|
||||
}
|
||||
const { body } = arrowFuncExpr.node;
|
||||
if (t.isBlockStatement(body)) {
|
||||
valDecl.replaceWith(t.functionDeclaration(id, arrowFuncExpr.node.params, body));
|
||||
}
|
||||
else {
|
||||
valDecl.replaceWith(t.functionDeclaration(id, arrowFuncExpr.node.params, t.blockStatement([
|
||||
t.returnStatement(body)
|
||||
])));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const functionDecl = path.findParent(p => p.isFunctionDeclaration());
|
||||
if (functionDecl && functionDecl.isFunctionDeclaration()) {
|
||||
const hasClassDecl = functionDecl.findParent(p => p.isClassDeclaration());
|
||||
if (hasClassDecl) {
|
||||
// @TODO: 加上链接
|
||||
throw utils_1.codeFrameError(functionDecl.node, '在类中的函数式组件请写成类函数式组件:参考:');
|
||||
}
|
||||
const { id, body, params } = functionDecl.node;
|
||||
let arg = null;
|
||||
if (params.length > 1) {
|
||||
throw utils_1.codeFrameError(id, '函数式组件的参数最多只能传入一个');
|
||||
}
|
||||
else if (params.length === 1) {
|
||||
arg = params[0];
|
||||
}
|
||||
const cloneBody = lodash_1.cloneDeep(body);
|
||||
if (!initialIsCapital(id.name)) {
|
||||
throw utils_1.codeFrameError(id, '组件命名规则请遵守帕斯卡命名法(Pascal Case)');
|
||||
}
|
||||
if (arg) {
|
||||
if (t.isIdentifier(arg)) {
|
||||
cloneBody.body.push(utils_1.buildConstVariableDeclaration(arg.name, t.memberExpression(t.thisExpression(), t.identifier('props'))));
|
||||
}
|
||||
else if (t.isObjectPattern(arg)) {
|
||||
cloneBody.body.push(t.variableDeclaration('const', [
|
||||
t.variableDeclarator(arg, t.memberExpression(t.thisExpression(), t.identifier('props')))
|
||||
]));
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(arg, '函数式组件只支持传入一个简单标识符或使用对象结构');
|
||||
}
|
||||
}
|
||||
const classDecl = t.classDeclaration(id, t.memberExpression(t.identifier('Taro'), t.identifier('Component')), t.classBody([
|
||||
t.classMethod('method', t.identifier('render'), [], cloneBody)
|
||||
]), []);
|
||||
functionDecl.replaceWith(classDecl);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=functional.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"functional.js","sourceRoot":"","sources":["../../src/functional.ts"],"names":[],"mappings":";;AACA,mCAAuE;AACvE,iCAAgC;AAChC,mCAAkC;AAElC,SAAS,gBAAgB,CAAE,IAAY;IACrC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;AAC1C,CAAC;AAEY,QAAA,mBAAmB,GAE5B,GAAG,EAAE;IACP,OAAO;QACL,OAAO,EAAE;YACP,UAAU,CAAE,IAAI;gBACd,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,yBAAyB,EAAE,CAAC,CAAA;gBACzE,IAAI,aAAa,IAAI,aAAa,CAAC,yBAAyB,EAAE,IAAI,aAAa,CAAC,UAAU,CAAC,oBAAoB,EAAE,EAAE;oBACjH,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,UAAU,CAAA;oBACnD,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE;wBACpC,MAAM,sBAAc,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;qBACrD;oBACD,MAAM,EAAE,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;oBAC3C,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE;wBACvB,MAAM,sBAAc,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAA;qBAC7C;oBACD,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;wBAC9B,MAAM,sBAAc,CAAC,EAAE,EAAE,8BAA8B,CAAC,CAAA;qBACzD;oBACD,MAAM,YAAY,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAA;oBAC1E,IAAI,YAAY,EAAE;wBAChB,cAAc;wBACd,MAAM,sBAAc,CAAC,aAAa,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;qBACnE;oBACD,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,IAAI,CAAA;oBACnC,IAAI,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE;wBAC5B,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;qBAChF;yBAAM;wBACL,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC;4BACxF,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC;yBACxB,CAAC,CAAC,CAAC,CAAA;qBACL;oBACD,OAAM;iBACP;gBAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAA;gBACpE,IAAI,YAAY,IAAI,YAAY,CAAC,qBAAqB,EAAE,EAAE;oBACxD,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAA;oBACzE,IAAI,YAAY,EAAE;wBAChB,cAAc;wBACd,MAAM,sBAAc,CAAC,YAAY,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;qBAClE;oBACD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAA;oBAC9C,IAAI,GAAG,GAAkB,IAAI,CAAA;oBAC7B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;wBACrB,MAAM,sBAAc,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAA;qBAC7C;yBAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;wBAC9B,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;qBAChB;oBACD,MAAM,SAAS,GAAG,kBAAS,CAAC,IAAI,CAAC,CAAA;oBACjC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;wBAC9B,MAAM,sBAAc,CAAC,EAAE,EAAE,8BAA8B,CAAC,CAAA;qBACzD;oBACD,IAAI,GAAG,EAAE;wBACP,IAAI,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE;4BACvB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,qCAA6B,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;yBAC5H;6BAAM,IAAI,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE;4BACjC,SAAS,CAAC,IAAI,CAAC,IAAI,CACjB,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE;gCAC7B,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;6BACzF,CAAC,CACH,CAAA;yBACF;6BAAM;4BACL,MAAM,sBAAc,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAA;yBACtD;qBACF;oBACD,MAAM,SAAS,GAAG,CAAC,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;wBACxH,CAAC,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC;qBAC/D,CAAC,EAAE,EAAE,CAAC,CAAA;oBACP,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;iBACpC;YACH,CAAC;SACF;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@ -0,0 +1,507 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const babel_traverse_1 = require("babel-traverse");
|
||||
const babel_generator_1 = require("babel-generator");
|
||||
const html_1 = require("html");
|
||||
const babel_core_1 = require("babel-core");
|
||||
const ts = require("typescript");
|
||||
const class_1 = require("./class");
|
||||
const utils_1 = require("./utils");
|
||||
const t = require("babel-types");
|
||||
const constant_1 = require("./constant");
|
||||
const adapter_1 = require("./adapter");
|
||||
const options_1 = require("./options");
|
||||
const lodash_1 = require("lodash");
|
||||
const template = require('babel-template');
|
||||
function getIdsFromMemberProps(member) {
|
||||
let ids = [];
|
||||
const { object, property } = member;
|
||||
if (t.isMemberExpression(object)) {
|
||||
ids = ids.concat(getIdsFromMemberProps(object));
|
||||
}
|
||||
if (t.isThisExpression(object)) {
|
||||
ids.push('this');
|
||||
}
|
||||
if (t.isIdentifier(object)) {
|
||||
ids.push(object.name);
|
||||
}
|
||||
if (t.isIdentifier(property)) {
|
||||
ids.push(property.name);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
/**
|
||||
* TS 编译器会把 class property 移到构造器,
|
||||
* 而小程序要求 `config` 和所有函数在初始化(after new Class)之后就收集到所有的函数和 config 信息,
|
||||
* 所以当如构造器里有 this.func = () => {...} 的形式,就给他转换成普通的 classProperty function
|
||||
* 如果有 config 就给他还原
|
||||
*/
|
||||
function resetTSClassProperty(body) {
|
||||
for (const method of body) {
|
||||
if (t.isClassMethod(method) && method.kind === 'constructor') {
|
||||
if (t.isBlockStatement(method.body)) {
|
||||
method.body.body = method.body.body.filter(statement => {
|
||||
if (t.isExpressionStatement(statement) && t.isAssignmentExpression(statement.expression)) {
|
||||
const expr = statement.expression;
|
||||
const { left, right } = expr;
|
||||
if (t.isMemberExpression(left) &&
|
||||
t.isThisExpression(left.object) &&
|
||||
t.isIdentifier(left.property)) {
|
||||
if ((t.isArrowFunctionExpression(right) || t.isFunctionExpression(right))
|
||||
||
|
||||
(left.property.name === 'config' && t.isObjectExpression(right))) {
|
||||
const classProp = t.classProperty(left.property, right);
|
||||
body.push(classProp);
|
||||
handleThirdPartyComponent(classProp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function findDeclarationScope(path, id) {
|
||||
const scopePath = path.findParent(p => !!p.scope.getOwnBindingIdentifier(id.name));
|
||||
if (scopePath) {
|
||||
return scopePath;
|
||||
}
|
||||
throw utils_1.codeFrameError(path.node, '该引用从未被定义');
|
||||
}
|
||||
function buildFullPathThisPropsRef(id, memberIds, path) {
|
||||
const scopePath = findDeclarationScope(path, id);
|
||||
const binding = scopePath.scope.getOwnBinding(id.name);
|
||||
if (binding) {
|
||||
const bindingPath = binding.path;
|
||||
if (bindingPath.isVariableDeclarator()) {
|
||||
const dclId = bindingPath.get('id');
|
||||
const dclInit = bindingPath.get('init');
|
||||
let dclInitIds = [];
|
||||
if (dclInit.isMemberExpression()) {
|
||||
dclInitIds = getIdsFromMemberProps(dclInit.node);
|
||||
if (dclId.isIdentifier()) {
|
||||
memberIds.shift();
|
||||
}
|
||||
if (dclInitIds[0] === 'this' && dclInitIds[1] === 'props') {
|
||||
return template(dclInitIds.concat(memberIds).join('.'))().expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function handleThirdPartyComponent(expr) {
|
||||
if (t.isClassProperty(expr) && expr.key.name === 'config' && t.isObjectExpression(expr.value)) {
|
||||
const properties = expr.value.properties;
|
||||
for (const prop of properties) {
|
||||
if (t.isObjectProperty(prop) &&
|
||||
(t.isIdentifier(prop.key, { name: 'usingComponents' }) || t.isStringLiteral(prop.key, { value: 'usingComponents' })) &&
|
||||
t.isObjectExpression(prop.value)) {
|
||||
for (const value of prop.value.properties) {
|
||||
if (t.isObjectProperty(value)) {
|
||||
if (t.isStringLiteral(value.key)) {
|
||||
constant_1.THIRD_PARTY_COMPONENTS.add(value.key.value);
|
||||
}
|
||||
if (t.isIdentifier(value.key)) {
|
||||
constant_1.THIRD_PARTY_COMPONENTS.add(value.key.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function transform(options) {
|
||||
if (options.adapter) {
|
||||
adapter_1.setAdapter(options.adapter);
|
||||
}
|
||||
if (adapter_1.Adapter.type === "swan" /* swan */) {
|
||||
constant_1.setLoopOriginal('privateOriginal');
|
||||
}
|
||||
constant_1.THIRD_PARTY_COMPONENTS.clear();
|
||||
const code = options.isTyped
|
||||
? ts.transpile(options.code, {
|
||||
jsx: ts.JsxEmit.Preserve,
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
importHelpers: true,
|
||||
noEmitHelpers: true
|
||||
})
|
||||
: options.code;
|
||||
options.env = Object.assign({ 'process.env.TARO_ENV': options.adapter || 'weapp' }, options.env || {});
|
||||
options_1.setTransformOptions(options);
|
||||
utils_1.setting.sourceCode = code;
|
||||
// babel-traverse 无法生成 Hub
|
||||
// 导致 Path#getSource|buildCodeFrameError 都无法直接使用
|
||||
// 原因大概是 babylon.parse 没有生成 File 实例导致 scope 和 path 原型上都没有 `file`
|
||||
// 将来升级到 babel@7 可以直接用 parse 而不是 transform
|
||||
const ast = babel_core_1.transform(code, options_1.buildBabelTransformOptions()).ast;
|
||||
if (options.isNormal) {
|
||||
return { ast };
|
||||
}
|
||||
// transformFromAst(ast, code)
|
||||
let result;
|
||||
const componentSourceMap = new Map();
|
||||
const imageSource = new Set();
|
||||
const importSources = new Set();
|
||||
let componentProperies = [];
|
||||
let mainClass;
|
||||
let storeName;
|
||||
let renderMethod;
|
||||
let isImportTaro = false;
|
||||
babel_traverse_1.default(ast, {
|
||||
TemplateLiteral(path) {
|
||||
const nodes = [];
|
||||
const { quasis, expressions } = path.node;
|
||||
let index = 0;
|
||||
if (path.parentPath.isTaggedTemplateExpression()) {
|
||||
return;
|
||||
}
|
||||
for (const elem of quasis) {
|
||||
if (elem.value.cooked) {
|
||||
nodes.push(t.stringLiteral(elem.value.cooked));
|
||||
}
|
||||
if (index < expressions.length) {
|
||||
const expr = expressions[index++];
|
||||
if (!t.isStringLiteral(expr, { value: '' })) {
|
||||
nodes.push(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// + 号连接符必须保证第一和第二个 node 都是字符串
|
||||
if (!t.isStringLiteral(nodes[0]) && !t.isStringLiteral(nodes[1])) {
|
||||
nodes.unshift(t.stringLiteral(''));
|
||||
}
|
||||
let root = nodes[0];
|
||||
for (let i = 1; i < nodes.length; i++) {
|
||||
root = t.binaryExpression('+', root, nodes[i]);
|
||||
}
|
||||
path.replaceWith(root);
|
||||
},
|
||||
ClassDeclaration(path) {
|
||||
mainClass = path;
|
||||
const superClass = utils_1.getSuperClassCode(path);
|
||||
if (superClass) {
|
||||
try {
|
||||
componentProperies = transform({
|
||||
isRoot: false,
|
||||
isApp: false,
|
||||
code: superClass.code,
|
||||
isTyped: true,
|
||||
sourcePath: superClass.sourcePath,
|
||||
outputPath: superClass.sourcePath
|
||||
}).componentProperies;
|
||||
}
|
||||
catch (error) {
|
||||
//
|
||||
}
|
||||
}
|
||||
},
|
||||
ClassExpression(path) {
|
||||
mainClass = path;
|
||||
},
|
||||
ClassMethod(path) {
|
||||
if (t.isIdentifier(path.node.key) && path.node.key.name === 'render') {
|
||||
renderMethod = path;
|
||||
}
|
||||
},
|
||||
IfStatement(path) {
|
||||
const consequent = path.get('consequent');
|
||||
if (!consequent.isBlockStatement()) {
|
||||
consequent.replaceWith(t.blockStatement([
|
||||
consequent.node
|
||||
]));
|
||||
}
|
||||
},
|
||||
CallExpression(path) {
|
||||
const callee = path.get('callee');
|
||||
if (utils_1.isContainJSXElement(path)) {
|
||||
return;
|
||||
}
|
||||
if (callee.isReferencedMemberExpression()) {
|
||||
const id = utils_1.findFirstIdentifierFromMemberExpression(callee.node);
|
||||
const property = callee.node.property;
|
||||
if (t.isIdentifier(property) && property.name.startsWith('on')) {
|
||||
const funcExpr = path.findParent(p => p.isFunctionExpression());
|
||||
if (funcExpr && funcExpr.isFunctionExpression()) {
|
||||
const taroAPI = funcExpr.findParent(p => p.isCallExpression() && t.isMemberExpression(p.node.callee) && t.isIdentifier(p.node.callee.object, { name: 'Taro' }));
|
||||
if (taroAPI && taroAPI.isCallExpression()) {
|
||||
throw utils_1.codeFrameError(funcExpr.node, '在回调函数使用从 props 传递的函数时,请把回调函数改造为箭头函数并一直使用 `this` 取值');
|
||||
}
|
||||
}
|
||||
}
|
||||
const calleeIds = getIdsFromMemberProps(callee.node);
|
||||
if (t.isIdentifier(id) && id.name.startsWith('on') && "alipay" /* alipay */ !== adapter_1.Adapter.type) {
|
||||
const fullPath = buildFullPathThisPropsRef(id, calleeIds, path);
|
||||
if (fullPath) {
|
||||
path.replaceWith(t.callExpression(fullPath, path.node.arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callee.isReferencedIdentifier()) {
|
||||
const id = callee.node;
|
||||
const ids = [id.name];
|
||||
if (t.isIdentifier(id) && id.name.startsWith('on')) {
|
||||
const funcExpr = path.findParent(p => p.isFunctionExpression());
|
||||
if (funcExpr && funcExpr.isFunctionExpression()) {
|
||||
const taroAPI = funcExpr.findParent(p => p.isCallExpression() && t.isMemberExpression(p.node.callee) && t.isIdentifier(p.node.callee.object, { name: 'Taro' }));
|
||||
if (taroAPI && taroAPI.isCallExpression()) {
|
||||
throw utils_1.codeFrameError(funcExpr.node, '在回调函数使用从 props 传递的函数时,请把回调函数改造为箭头函数并一直使用 `this` 取值');
|
||||
}
|
||||
}
|
||||
const fullPath = buildFullPathThisPropsRef(id, ids, path);
|
||||
if (fullPath) {
|
||||
path.replaceWith(t.callExpression(fullPath, path.node.arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// JSXIdentifier (path) {
|
||||
// const parentPath = path.parentPath
|
||||
// if (!parentPath.isJSXAttribute()) {
|
||||
// return
|
||||
// }
|
||||
// const element = parentPath.parentPath
|
||||
// if (!element.isJSXOpeningElement()) {
|
||||
// return
|
||||
// }
|
||||
// const elementName = element.get('name')
|
||||
// if (!elementName.isJSXIdentifier()) {
|
||||
// return
|
||||
// }
|
||||
// if (DEFAULT_Component_SET.has(elementName.node.name)) {
|
||||
// return
|
||||
// }
|
||||
// const expr = parentPath.get('value.expression')
|
||||
// },
|
||||
JSXElement(path) {
|
||||
const assignment = path.findParent(p => p.isAssignmentExpression());
|
||||
if (assignment && assignment.isAssignmentExpression() && !options.isTyped) {
|
||||
const left = assignment.node.left;
|
||||
if (t.isIdentifier(left)) {
|
||||
const binding = assignment.scope.getBinding(left.name);
|
||||
if (binding && binding.scope === assignment.scope) {
|
||||
if (binding.path.isVariableDeclarator()) {
|
||||
binding.path.node.init = path.node;
|
||||
assignment.remove();
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(path.node, '同一个作用域的JSX 变量延时赋值没有意义。详见:https://github.com/NervJS/taro/issues/550');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const switchStatement = path.findParent(p => p.isSwitchStatement());
|
||||
if (switchStatement && switchStatement.isSwitchStatement()) {
|
||||
const { discriminant, cases } = switchStatement.node;
|
||||
const ifStatement = cases.map((Case, index) => {
|
||||
const [consequent] = Case.consequent;
|
||||
if (!t.isBlockStatement(consequent)) {
|
||||
throw utils_1.codeFrameError(switchStatement.node, '含有 JSX 的 switch case 语句必须每种情况都用花括号 `{}` 包裹结果');
|
||||
}
|
||||
const block = t.blockStatement(consequent.body.filter(b => !t.isBreakStatement(b)));
|
||||
if (index !== cases.length - 1 && t.isNullLiteral(Case.test)) {
|
||||
throw utils_1.codeFrameError(Case, '含有 JSX 的 switch case 语句只有最后一个 case 才能是 default');
|
||||
}
|
||||
const test = Case.test === null ? t.nullLiteral() : t.binaryExpression('===', discriminant, Case.test);
|
||||
return { block, test };
|
||||
}).reduceRight((ifStatement, item) => {
|
||||
if (t.isNullLiteral(item.test)) {
|
||||
ifStatement.alternate = item.block;
|
||||
return ifStatement;
|
||||
}
|
||||
const newStatement = t.ifStatement(item.test, item.block, t.isBooleanLiteral(ifStatement.test, { value: false })
|
||||
? ifStatement.alternate
|
||||
: ifStatement);
|
||||
return newStatement;
|
||||
}, t.ifStatement(t.booleanLiteral(false), t.blockStatement([])));
|
||||
switchStatement.insertAfter(ifStatement);
|
||||
switchStatement.remove();
|
||||
}
|
||||
const isForStatement = (p) => p && (p.isForStatement() || p.isForInStatement() || p.isForOfStatement());
|
||||
const forStatement = path.findParent(isForStatement);
|
||||
if (isForStatement(forStatement)) {
|
||||
throw utils_1.codeFrameError(forStatement.node, '不行使用 for 循环操作 JSX 元素,详情:https://github.com/NervJS/taro/blob/master/packages/eslint-plugin-taro/docs/manipulate-jsx-as-array.md');
|
||||
}
|
||||
const loopCallExpr = path.findParent(p => utils_1.isArrayMapCallExpression(p));
|
||||
if (loopCallExpr && loopCallExpr.isCallExpression()) {
|
||||
const [func] = loopCallExpr.node.arguments;
|
||||
if (t.isArrowFunctionExpression(func) && !t.isBlockStatement(func.body)) {
|
||||
func.body = t.blockStatement([
|
||||
t.returnStatement(func.body)
|
||||
]);
|
||||
}
|
||||
}
|
||||
},
|
||||
JSXOpeningElement(path) {
|
||||
const { name } = path.node.name;
|
||||
const binding = path.scope.getBinding(name);
|
||||
if (process.env.NODE_ENV !== 'test' && constant_1.DEFAULT_Component_SET.has(name) && binding && binding.kind === 'module') {
|
||||
const bindingPath = binding.path;
|
||||
if (bindingPath.parentPath.isImportDeclaration()) {
|
||||
const source = bindingPath.parentPath.node.source;
|
||||
if (source.value !== constant_1.COMPONENTS_PACKAGE_NAME) {
|
||||
throw utils_1.codeFrameError(bindingPath.parentPath.node, `内置组件名: '${name}' 只能从 ${constant_1.COMPONENTS_PACKAGE_NAME} 引入。`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name === 'Provider') {
|
||||
const modules = path.scope.getAllBindings('module');
|
||||
const providerBinding = Object.values(modules).some((m) => m.identifier.name === 'Provider');
|
||||
if (providerBinding) {
|
||||
path.node.name = t.jSXIdentifier('view');
|
||||
const store = path.node.attributes.find(attr => attr.name.name === 'store');
|
||||
if (store && t.isJSXExpressionContainer(store.value) && t.isIdentifier(store.value.expression)) {
|
||||
storeName = store.value.expression.name;
|
||||
}
|
||||
path.node.attributes = [];
|
||||
}
|
||||
}
|
||||
if (constant_1.IMAGE_COMPONENTS.has(name)) {
|
||||
for (const attr of path.node.attributes) {
|
||||
if (attr.name.name === 'src') {
|
||||
if (t.isStringLiteral(attr.value)) {
|
||||
imageSource.add(attr.value.value);
|
||||
}
|
||||
else if (t.isJSXExpressionContainer(attr.value)) {
|
||||
if (t.isStringLiteral(attr.value.expression)) {
|
||||
imageSource.add(attr.value.expression.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
JSXAttribute(path) {
|
||||
const { name, value } = path.node;
|
||||
if (options.jsxAttributeNameReplace) {
|
||||
for (const r in options.jsxAttributeNameReplace) {
|
||||
if (options.jsxAttributeNameReplace.hasOwnProperty(r)) {
|
||||
const element = options.jsxAttributeNameReplace[r];
|
||||
if (t.isJSXIdentifier(name, { name: r })) {
|
||||
path.node.name = t.jSXIdentifier(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!t.isJSXIdentifier(name) || value === null || t.isStringLiteral(value) || t.isJSXElement(value)) {
|
||||
return;
|
||||
}
|
||||
const expr = value.expression;
|
||||
const exprPath = path.get('value.expression');
|
||||
const classDecl = path.findParent(p => p.isClassDeclaration());
|
||||
const classDeclName = classDecl && classDecl.isClassDeclaration() && lodash_1.get(classDecl, 'node.id.name', '');
|
||||
let isConverted = false;
|
||||
if (classDeclName) {
|
||||
isConverted = classDeclName === '_C' || classDeclName.endsWith('Tmpl');
|
||||
}
|
||||
if (!t.isBinaryExpression(expr, { operator: '+' }) && !t.isLiteral(expr) && name.name === 'style' && !isConverted) {
|
||||
const jsxID = path.findParent(p => p.isJSXOpeningElement()).get('name');
|
||||
if (jsxID && jsxID.isJSXIdentifier() && constant_1.DEFAULT_Component_SET.has(jsxID.node.name)) {
|
||||
exprPath.replaceWith(t.callExpression(t.identifier(constant_1.INTERNAL_INLINE_STYLE), [expr]));
|
||||
}
|
||||
}
|
||||
if (name.name.startsWith('on')) {
|
||||
if (exprPath.isReferencedIdentifier()) {
|
||||
const ids = [expr.name];
|
||||
const fullPath = buildFullPathThisPropsRef(expr, ids, path);
|
||||
if (fullPath) {
|
||||
exprPath.replaceWith(fullPath);
|
||||
}
|
||||
}
|
||||
if (exprPath.isReferencedMemberExpression()) {
|
||||
const id = utils_1.findFirstIdentifierFromMemberExpression(expr);
|
||||
const ids = getIdsFromMemberProps(expr);
|
||||
if (t.isIdentifier(id)) {
|
||||
const fullPath = buildFullPathThisPropsRef(id, ids, path);
|
||||
if (fullPath) {
|
||||
exprPath.replaceWith(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
// @TODO: bind 的处理待定
|
||||
}
|
||||
},
|
||||
ImportDeclaration(path) {
|
||||
const source = path.node.source.value;
|
||||
if (importSources.has(source)) {
|
||||
throw utils_1.codeFrameError(path.node, '无法在同一文件重复 import 相同的包。');
|
||||
}
|
||||
else {
|
||||
importSources.add(source);
|
||||
}
|
||||
const names = [];
|
||||
if (source === constant_1.TARO_PACKAGE_NAME) {
|
||||
isImportTaro = true;
|
||||
path.node.specifiers.push(t.importSpecifier(t.identifier(constant_1.INTERNAL_SAFE_GET), t.identifier(constant_1.INTERNAL_SAFE_GET)), t.importSpecifier(t.identifier(constant_1.INTERNAL_GET_ORIGNAL), t.identifier(constant_1.INTERNAL_GET_ORIGNAL)), t.importSpecifier(t.identifier(constant_1.INTERNAL_INLINE_STYLE), t.identifier(constant_1.INTERNAL_INLINE_STYLE)), t.importSpecifier(t.identifier(constant_1.GEL_ELEMENT_BY_ID), t.identifier(constant_1.GEL_ELEMENT_BY_ID)));
|
||||
}
|
||||
if (source === constant_1.REDUX_PACKAGE_NAME || source === constant_1.MOBX_PACKAGE_NAME) {
|
||||
path.node.specifiers.forEach((s, index, specs) => {
|
||||
if (s.local.name === 'Provider') {
|
||||
specs.splice(index, 1);
|
||||
specs.push(t.importSpecifier(t.identifier('setStore'), t.identifier('setStore')));
|
||||
}
|
||||
});
|
||||
}
|
||||
path.traverse({
|
||||
ImportDefaultSpecifier(path) {
|
||||
const name = path.node.local.name;
|
||||
names.push(name);
|
||||
},
|
||||
ImportSpecifier(path) {
|
||||
const name = path.node.imported.name;
|
||||
names.push(name);
|
||||
if (source === constant_1.TARO_PACKAGE_NAME && name === 'Component') {
|
||||
path.node.local = t.identifier('__BaseComponent');
|
||||
}
|
||||
}
|
||||
});
|
||||
componentSourceMap.set(source, names);
|
||||
}
|
||||
});
|
||||
if (!isImportTaro) {
|
||||
ast.program.body.unshift(t.importDeclaration([
|
||||
t.importDefaultSpecifier(t.identifier('Taro')),
|
||||
t.importSpecifier(t.identifier(constant_1.INTERNAL_SAFE_GET), t.identifier(constant_1.INTERNAL_SAFE_GET)),
|
||||
t.importSpecifier(t.identifier(constant_1.INTERNAL_GET_ORIGNAL), t.identifier(constant_1.INTERNAL_GET_ORIGNAL)),
|
||||
t.importSpecifier(t.identifier(constant_1.INTERNAL_INLINE_STYLE), t.identifier(constant_1.INTERNAL_INLINE_STYLE))
|
||||
], t.stringLiteral('@tarojs/taro')));
|
||||
}
|
||||
if (!mainClass) {
|
||||
throw new Error('未找到 Taro.Component 的类定义');
|
||||
}
|
||||
mainClass.node.body.body.forEach(handleThirdPartyComponent);
|
||||
const storeBinding = mainClass.scope.getBinding(storeName);
|
||||
mainClass.scope.rename('Component', '__BaseComponent');
|
||||
if (storeBinding) {
|
||||
const statementPath = storeBinding.path.getStatementParent();
|
||||
if (statementPath) {
|
||||
ast.program.body.forEach((node, index, body) => {
|
||||
if (node === statementPath.node) {
|
||||
body.splice(index + 1, 0, t.expressionStatement(t.callExpression(t.identifier('setStore'), [
|
||||
t.identifier(storeName)
|
||||
])));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
resetTSClassProperty(mainClass.node.body.body);
|
||||
if (options.isApp) {
|
||||
renderMethod.replaceWith(t.classMethod('method', t.identifier('_createData'), [], t.blockStatement([])));
|
||||
return { ast };
|
||||
}
|
||||
result = new class_1.Transformer(mainClass, options.sourcePath, componentProperies).result;
|
||||
result.code = babel_generator_1.default(ast).code;
|
||||
result.ast = ast;
|
||||
const lessThanSignReg = new RegExp(constant_1.lessThanSignPlacehold, 'g');
|
||||
result.compressedTemplate = result.template;
|
||||
result.template = html_1.prettyPrint(result.template, {
|
||||
max_char: 0,
|
||||
unformatted: process.env.NODE_ENV === 'test' ? [] : ['text']
|
||||
});
|
||||
result.template = result.template.replace(lessThanSignReg, '<');
|
||||
result.imageSrcs = Array.from(imageSource);
|
||||
return result;
|
||||
}
|
||||
exports.default = transform;
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,258 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const babel_generator_1 = require("babel-generator");
|
||||
const t = require("babel-types");
|
||||
const lodash_1 = require("lodash");
|
||||
const constant_1 = require("./constant");
|
||||
const create_html_element_1 = require("./create-html-element");
|
||||
const utils_1 = require("./utils");
|
||||
const adapter_1 = require("./adapter");
|
||||
function isStartWithWX(str) {
|
||||
return str[0] === 'w' && str[1] === 'x';
|
||||
}
|
||||
exports.isStartWithWX = isStartWithWX;
|
||||
const specialComponentName = ['block', 'Block', 'slot', 'Slot'];
|
||||
function removeJSXThisProperty(path) {
|
||||
if (!path.parentPath.isCallExpression()) {
|
||||
const p = path.getSibling('property');
|
||||
if (p.isIdentifier({ name: 'props' }) ||
|
||||
p.isIdentifier({ name: 'state' })) {
|
||||
path.parentPath.replaceWithSourceString('this');
|
||||
}
|
||||
else {
|
||||
path.parentPath.replaceWith(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.removeJSXThisProperty = removeJSXThisProperty;
|
||||
function findJSXAttrByName(attrs, name) {
|
||||
for (const attr of attrs) {
|
||||
if (!t.isJSXIdentifier(attr.name)) {
|
||||
break;
|
||||
}
|
||||
if (attr.name.name === name) {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.findJSXAttrByName = findJSXAttrByName;
|
||||
function buildRefTemplate(name, refName, loop, key) {
|
||||
const attrs = [
|
||||
t.jSXAttribute(t.jSXIdentifier('is'), t.stringLiteral(name)),
|
||||
t.jSXAttribute(t.jSXIdentifier('data'), t.stringLiteral(`{{...${refName ? `${loop ? '' : '$$'}${refName}` : '__data'}}}`))
|
||||
];
|
||||
if (key) {
|
||||
attrs.push(key);
|
||||
}
|
||||
return t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('template'), attrs), t.jSXClosingElement(t.jSXIdentifier('template')), []);
|
||||
}
|
||||
exports.buildRefTemplate = buildRefTemplate;
|
||||
function buildJSXAttr(name, value) {
|
||||
return t.jSXAttribute(t.jSXIdentifier(name), t.jSXExpressionContainer(value));
|
||||
}
|
||||
exports.buildJSXAttr = buildJSXAttr;
|
||||
function newJSXIfAttr(jsx, value) {
|
||||
jsx.openingElement.attributes.push(buildJSXAttr(adapter_1.Adapter.if, value));
|
||||
}
|
||||
exports.newJSXIfAttr = newJSXIfAttr;
|
||||
function setJSXAttr(jsx, name, value, path) {
|
||||
const element = jsx.openingElement;
|
||||
if (!t.isJSXIdentifier(element.name)) {
|
||||
return;
|
||||
}
|
||||
if (element.name.name === 'Block' || element.name.name === 'block' || !path) {
|
||||
jsx.openingElement.attributes.push(t.jSXAttribute(t.jSXIdentifier(name), value));
|
||||
}
|
||||
else {
|
||||
const block = buildBlockElement();
|
||||
setJSXAttr(block, name, value);
|
||||
block.children = [jsx];
|
||||
path.node = block;
|
||||
}
|
||||
}
|
||||
exports.setJSXAttr = setJSXAttr;
|
||||
function isAllLiteral(...args) {
|
||||
return args.every(p => t.isLiteral(p));
|
||||
}
|
||||
exports.isAllLiteral = isAllLiteral;
|
||||
function buildBlockElement() {
|
||||
return t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('block'), []), t.jSXClosingElement(t.jSXIdentifier('block')), []);
|
||||
}
|
||||
exports.buildBlockElement = buildBlockElement;
|
||||
function parseJSXChildren(children) {
|
||||
return children
|
||||
.filter(child => {
|
||||
return !(t.isJSXText(child) && child.value.trim() === '');
|
||||
})
|
||||
.reduce((str, child) => {
|
||||
if (t.isJSXText(child)) {
|
||||
const strings = [];
|
||||
child.value.split(/(\r?\n\s*)/).forEach((val) => {
|
||||
const value = val.replace(/\u00a0/g, ' ').trimLeft();
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
if (value.startsWith('\n')) {
|
||||
return;
|
||||
}
|
||||
strings.push(value);
|
||||
});
|
||||
return str + strings.join('');
|
||||
}
|
||||
if (t.isJSXElement(child)) {
|
||||
return str + parseJSXElement(child);
|
||||
}
|
||||
if (t.isJSXExpressionContainer(child)) {
|
||||
if (t.isJSXElement(child.expression)) {
|
||||
return str + parseJSXElement(child.expression);
|
||||
}
|
||||
return str + `{${utils_1.decodeUnicode(babel_generator_1.default(child, {
|
||||
quotes: 'single',
|
||||
jsonCompatibleStrings: true
|
||||
})
|
||||
.code)
|
||||
.replace(/(this\.props\.)|(this\.state\.)/g, '')
|
||||
.replace(/(props\.)|(state\.)/g, '')
|
||||
.replace(/this\./g, '')
|
||||
.replace(/</g, constant_1.lessThanSignPlacehold)}}`;
|
||||
}
|
||||
return str;
|
||||
}, '');
|
||||
}
|
||||
function parseJSXElement(element) {
|
||||
const children = element.children;
|
||||
const { attributes, name } = element.openingElement;
|
||||
const TRIGGER_OBSERER = adapter_1.Adapter.type === "swan" /* swan */ ? 'privateTriggerObserer' : '__triggerObserer';
|
||||
if (t.isJSXMemberExpression(name)) {
|
||||
throw utils_1.codeFrameError(name.loc, '暂不支持 JSX 成员表达式');
|
||||
}
|
||||
const componentName = name.name;
|
||||
const isDefaultComponent = constant_1.DEFAULT_Component_SET.has(componentName);
|
||||
const componentSpecialProps = constant_1.SPECIAL_COMPONENT_PROPS.get(componentName);
|
||||
const componentTransfromProps = constant_1.TRANSFORM_COMPONENT_PROPS.get(adapter_1.Adapter.type);
|
||||
let hasElseAttr = false;
|
||||
attributes.forEach((a, index) => {
|
||||
if (a.name.name === adapter_1.Adapter.else && !['block', 'Block'].includes(componentName) && !isDefaultComponent) {
|
||||
hasElseAttr = true;
|
||||
attributes.splice(index, 1);
|
||||
}
|
||||
});
|
||||
if (hasElseAttr) {
|
||||
return create_html_element_1.createHTMLElement({
|
||||
name: 'block',
|
||||
attributes: {
|
||||
[adapter_1.Adapter.else]: true
|
||||
},
|
||||
value: parseJSXChildren([element])
|
||||
});
|
||||
}
|
||||
let attributesTrans = {};
|
||||
if (attributes.length) {
|
||||
attributesTrans = attributes.reduce((obj, attr) => {
|
||||
if (t.isJSXSpreadAttribute(attr)) {
|
||||
throw utils_1.codeFrameError(attr.loc, 'JSX 参数暂不支持 ...spread 表达式');
|
||||
}
|
||||
let name = attr.name.name;
|
||||
if (constant_1.DEFAULT_Component_SET.has(componentName)) {
|
||||
if (name === 'className') {
|
||||
name = 'class';
|
||||
}
|
||||
}
|
||||
let value = true;
|
||||
let attrValue = attr.value;
|
||||
if (typeof name === 'string') {
|
||||
const isAlipayEvent = adapter_1.Adapter.type === "alipay" /* alipay */ && /(^on[A-Z_])|(^catch[A-Z_])/.test(name);
|
||||
if (t.isStringLiteral(attrValue)) {
|
||||
value = attrValue.value;
|
||||
}
|
||||
else if (t.isJSXExpressionContainer(attrValue)) {
|
||||
let isBindEvent = (name.startsWith('bind') && name !== 'bind') || (name.startsWith('catch') && name !== 'catch');
|
||||
let code = utils_1.decodeUnicode(babel_generator_1.default(attrValue.expression, {
|
||||
quotes: 'single',
|
||||
concise: true
|
||||
}).code)
|
||||
.replace(/"/g, "'")
|
||||
.replace(/(this\.props\.)|(this\.state\.)/g, '')
|
||||
.replace(/this\./g, '');
|
||||
if ("swan" /* swan */ === adapter_1.Adapter.type &&
|
||||
code !== 'true' &&
|
||||
code !== 'false' &&
|
||||
constant_1.swanSpecialAttrs[componentName] &&
|
||||
constant_1.swanSpecialAttrs[componentName].includes(name)) {
|
||||
value = `{= ${code} =}`;
|
||||
}
|
||||
else {
|
||||
if (adapter_1.Adapter.key === name) {
|
||||
const splitCode = code.split('.');
|
||||
if (splitCode.length > 1) {
|
||||
value = splitCode.slice(1).join('.');
|
||||
}
|
||||
else {
|
||||
value = code;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = isBindEvent || isAlipayEvent ? code : `{{${code}}}`;
|
||||
}
|
||||
}
|
||||
if (adapter_1.Adapter.type === "swan" /* swan */ && name === adapter_1.Adapter.for) {
|
||||
value = code;
|
||||
}
|
||||
if (t.isStringLiteral(attrValue.expression)) {
|
||||
value = attrValue.expression.value;
|
||||
}
|
||||
}
|
||||
else if (attrValue === null && name !== adapter_1.Adapter.else) {
|
||||
value = `{{true}}`;
|
||||
}
|
||||
if (constant_1.THIRD_PARTY_COMPONENTS.has(componentName) && /^bind/.test(name) && name.includes('-')) {
|
||||
name = name.replace(/^bind/, 'bind:');
|
||||
}
|
||||
if (componentTransfromProps && componentTransfromProps[componentName]) {
|
||||
const transfromProps = componentTransfromProps[componentName];
|
||||
Object.keys(transfromProps).forEach(oriName => {
|
||||
if (transfromProps.hasOwnProperty(name)) {
|
||||
name = transfromProps[oriName];
|
||||
}
|
||||
});
|
||||
}
|
||||
if ((componentName === 'Input' || componentName === 'input') && name === 'maxLength') {
|
||||
obj['maxlength'] = value;
|
||||
}
|
||||
else if (componentSpecialProps && componentSpecialProps.has(name) ||
|
||||
name.startsWith('__fn_') ||
|
||||
isAlipayEvent) {
|
||||
obj[name] = value;
|
||||
}
|
||||
else {
|
||||
obj[isDefaultComponent && !name.includes('-') && !name.includes(':') ? lodash_1.kebabCase(name) : name] = value;
|
||||
}
|
||||
}
|
||||
// if (!isDefaultComponent && !specialComponentName.includes(componentName)) {
|
||||
// obj[TRIGGER_OBSERER] = '{{ _triggerObserer }}';
|
||||
// }
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
// else if (!isDefaultComponent && !specialComponentName.includes(componentName)) {
|
||||
// attributesTrans[TRIGGER_OBSERER] = '{{ _triggerObserer }}';
|
||||
// }
|
||||
return create_html_element_1.createHTMLElement({
|
||||
name: lodash_1.kebabCase(componentName),
|
||||
attributes: attributesTrans,
|
||||
value: parseJSXChildren(children)
|
||||
});
|
||||
}
|
||||
exports.parseJSXElement = parseJSXElement;
|
||||
function generateHTMLTemplate(template, name) {
|
||||
return create_html_element_1.createHTMLElement({
|
||||
name: 'template',
|
||||
attributes: {
|
||||
name
|
||||
},
|
||||
value: parseJSXElement(template)
|
||||
});
|
||||
}
|
||||
exports.generateHTMLTemplate = generateHTMLTemplate;
|
||||
//# sourceMappingURL=jsx.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,33 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Lifecycle;
|
||||
(function (Lifecycle) {
|
||||
Lifecycle["constructor"] = "constructor";
|
||||
Lifecycle["componentWillMount"] = "componentWillMount";
|
||||
Lifecycle["componentDidMount"] = "componentDidMount";
|
||||
Lifecycle["componentWillUpdate"] = "componentWillUpdate";
|
||||
Lifecycle["componentDidUpdate"] = "componentDidUpdate";
|
||||
Lifecycle["componentWillUnmount"] = "componentWillUnmount";
|
||||
Lifecycle["componentDidCatch"] = "componentDidCatch";
|
||||
Lifecycle["componentDidShow"] = "componentDidShow";
|
||||
Lifecycle["componentDidHide"] = "componentDidHide";
|
||||
Lifecycle["componentDidAttached"] = "componentDidAttached";
|
||||
Lifecycle["componentDidMoved"] = "componentDidMoved";
|
||||
Lifecycle["shouldComponentUpdate"] = "shouldComponentUpdate";
|
||||
Lifecycle["componentWillReceiveProps"] = "componentWillReceiveProps";
|
||||
})(Lifecycle = exports.Lifecycle || (exports.Lifecycle = {}));
|
||||
exports.PageLifecycle = {
|
||||
[Lifecycle.componentDidMount]: 'onLaunch',
|
||||
[Lifecycle.componentWillMount]: 'onLoad',
|
||||
[Lifecycle.componentWillUnmount]: 'onUnload',
|
||||
[Lifecycle.componentDidShow]: 'onShow',
|
||||
[Lifecycle.componentDidHide]: 'onHide'
|
||||
};
|
||||
exports.ComponentLifeCycle = {
|
||||
[Lifecycle.componentWillMount]: 'created',
|
||||
[Lifecycle.componentDidAttached]: 'attached',
|
||||
[Lifecycle.componentDidMount]: 'ready',
|
||||
[Lifecycle.componentDidMoved]: 'moved',
|
||||
[Lifecycle.componentWillUnmount]: 'detached'
|
||||
};
|
||||
//# sourceMappingURL=lifecycle.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":";;AAAA,IAAY,SAcX;AAdD,WAAY,SAAS;IACnB,wCAA2B,CAAA;IAC3B,sDAAyC,CAAA;IACzC,oDAAuC,CAAA;IACvC,wDAA2C,CAAA;IAC3C,sDAAyC,CAAA;IACzC,0DAA6C,CAAA;IAC7C,oDAAuC,CAAA;IACvC,kDAAqC,CAAA;IACrC,kDAAqC,CAAA;IACrC,0DAA6C,CAAA;IAC7C,oDAAuC,CAAA;IACvC,4DAA+C,CAAA;IAC/C,oEAAuD,CAAA;AACzD,CAAC,EAdW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAcpB;AAEY,QAAA,aAAa,GAAG;IAC3B,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAE,UAAU;IACzC,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,QAAQ;IACxC,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,UAAU;IAC5C,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,QAAQ;IACtC,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,QAAQ;CACvC,CAAA;AAEY,QAAA,kBAAkB,GAAG;IAChC,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,SAAS;IACzC,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,UAAU;IAC5C,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAE,OAAO;IACtC,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAE,OAAO;IACtC,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,UAAU;CAC7C,CAAA"}
|
|
@ -0,0 +1,227 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const t = require("babel-types");
|
||||
const utils_1 = require("./utils");
|
||||
const jsx_1 = require("./jsx");
|
||||
const constant_1 = require("./constant");
|
||||
const adapter_1 = require("./adapter");
|
||||
// @TODO
|
||||
// 重构 parseRender 和 parseLoop 失败
|
||||
// 尚不清楚 babel 的 state 和 context 传参机制
|
||||
// 目前先写两份代码,有时间看看 babel 具体对 state 和 context 做了什么导致传参失败
|
||||
function parseLoopBody(body, jsxDeclarations,
|
||||
// @TODO
|
||||
// 把 templates 换成 Map 可以支持 shalow variables declared
|
||||
// 现在先用 ESLint 的 no-shalow 顶着
|
||||
templates, loopScopes, finalReturnElement, returnedPaths) {
|
||||
const bodyScope = body.scope;
|
||||
body.traverse({
|
||||
JSXElement(jsxElementPath) {
|
||||
const parentNode = jsxElementPath.parent;
|
||||
const parentPath = jsxElementPath.parentPath;
|
||||
const isFinalReturn = jsxElementPath.getFunctionParent().isClassMethod();
|
||||
const isJSXChildren = t.isJSXElement(parentNode);
|
||||
if (!isJSXChildren) {
|
||||
let statementParent = jsxElementPath.getStatementParent();
|
||||
if (!(statementParent.isVariableDeclaration() ||
|
||||
statementParent.isExpressionStatement())) {
|
||||
statementParent = statementParent.findParent(s => s.isVariableDeclaration() || s.isExpressionStatement());
|
||||
}
|
||||
jsxDeclarations.add(statementParent);
|
||||
if (t.isVariableDeclarator(parentNode)) {
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
// setTemplate(name, path, templates)
|
||||
name && templates.set(name, jsxElementPath.node);
|
||||
}
|
||||
}
|
||||
else if (t.isLogicalExpression(parentNode)) {
|
||||
const { left, operator } = parentNode;
|
||||
if (operator === '&&') {
|
||||
if (t.isExpression(left)) {
|
||||
utils_1.newJSXIfAttr(jsxElementPath.node, left);
|
||||
parentPath.replaceWith(jsxElementPath.node);
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
utils_1.setTemplate(name, jsxElementPath, templates);
|
||||
// name && templates.set(name, path.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t.isConditionalExpression(parentNode)) {
|
||||
const { test, consequent, alternate } = parentNode;
|
||||
const block = jsx_1.buildBlockElement();
|
||||
if (t.isJSXElement(consequent) && t.isLiteral(alternate)) {
|
||||
const { value, confident } = parentPath.get('alternate').evaluate();
|
||||
if (confident && !value) {
|
||||
utils_1.newJSXIfAttr(block, test);
|
||||
block.children = [jsxElementPath.node];
|
||||
// newJSXIfAttr(jsxElementPath.node, test)
|
||||
parentPath.replaceWith(block);
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
utils_1.setTemplate(name, jsxElementPath, templates);
|
||||
// name && templates.set(name, path.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t.isLiteral(consequent) && t.isJSXElement(consequent)) {
|
||||
if (t.isNullLiteral(consequent)) {
|
||||
utils_1.newJSXIfAttr(block, utils_1.reverseBoolean(test));
|
||||
// newJSXIfAttr(jsxElementPath.node, reverseBoolean(test))
|
||||
parentPath.replaceWith(block);
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
utils_1.setTemplate(name, jsxElementPath, templates);
|
||||
// name && templates.set(name, path.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t.isJSXElement(consequent) && t.isJSXElement(alternate)) {
|
||||
const block2 = jsx_1.buildBlockElement();
|
||||
block.children = [consequent];
|
||||
utils_1.newJSXIfAttr(block, test);
|
||||
jsx_1.setJSXAttr(block2, adapter_1.Adapter.else);
|
||||
block2.children = [alternate];
|
||||
const parentBlock = jsx_1.buildBlockElement();
|
||||
parentBlock.children = [block, block2];
|
||||
parentPath.replaceWith(parentBlock);
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
utils_1.setTemplate(name, jsxElementPath, templates);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// console.log('todo')
|
||||
}
|
||||
}
|
||||
else if (t.isReturnStatement(parentNode)) {
|
||||
if (!isFinalReturn) {
|
||||
const caller = parentPath.findParent(p => p.isCallExpression());
|
||||
if (caller.isCallExpression()) {
|
||||
const callee = caller.node.callee;
|
||||
if (t.isMemberExpression(callee) &&
|
||||
t.isIdentifier(callee.property) &&
|
||||
callee.property.name === 'map') {
|
||||
let ary = callee.object;
|
||||
const blockStatementPath = parentPath.findParent(p => p.isBlockStatement());
|
||||
const body = blockStatementPath.node.body;
|
||||
let stateToBeAssign = new Set();
|
||||
for (const statement of body) {
|
||||
if (t.isVariableDeclaration(statement)) {
|
||||
for (const dcl of statement.declarations) {
|
||||
if (t.isIdentifier(dcl.id)) {
|
||||
const scope = blockStatementPath.scope;
|
||||
const stateName = scope.generateUid(constant_1.LOOP_STATE);
|
||||
stateToBeAssign.add(stateName);
|
||||
blockStatementPath.scope.rename(dcl.id.name, stateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t.isCallExpression(ary) || utils_1.isContainFunction(caller.get('callee').get('object'))) {
|
||||
const variableName = `anonymousState_${bodyScope.generateUid()}`;
|
||||
caller.getStatementParent().insertBefore(utils_1.buildConstVariableDeclaration(variableName, ary));
|
||||
ary = t.identifier(variableName);
|
||||
}
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.for, t.jSXExpressionContainer(ary));
|
||||
const [func] = caller.node.arguments;
|
||||
if (t.isFunctionExpression(func) ||
|
||||
t.isArrowFunctionExpression(func)) {
|
||||
const [item, index] = func.params;
|
||||
if (t.isIdentifier(item)) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.forItem, t.stringLiteral(item.name));
|
||||
loopScopes.add(item.name);
|
||||
}
|
||||
else {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.forItem, t.stringLiteral('__item'));
|
||||
}
|
||||
if (t.isIdentifier(index)) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.forIndex, t.stringLiteral(index.name));
|
||||
loopScopes.add(index.name);
|
||||
}
|
||||
caller.replaceWith(jsxElementPath.node);
|
||||
if (statementParent) {
|
||||
const name = utils_1.findIdentifierFromStatement(statementParent.node);
|
||||
// setTemplate(name, path, templates)
|
||||
name && templates.set(name, jsxElementPath.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const ifStatement = parentPath.findParent(p => p.isIfStatement());
|
||||
const blockStatement = parentPath.findParent(p => p.isBlockStatement());
|
||||
const block = finalReturnElement || jsx_1.buildBlockElement();
|
||||
if (utils_1.isBlockIfStatement(ifStatement, blockStatement)) {
|
||||
const { test, alternate, consequent } = ifStatement.node;
|
||||
if (alternate === blockStatement.node) {
|
||||
throw utils_1.codeFrameError(parentNode.loc, '不必要的 else 分支,请遵从 ESLint consistent-return: https://eslint.org/docs/rules/consistent-return');
|
||||
}
|
||||
else if (consequent === blockStatement.node) {
|
||||
const parentIfStatement = ifStatement.findParent(p => p.isIfStatement());
|
||||
if (parentIfStatement) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.elseif, t.jSXExpressionContainer(test));
|
||||
}
|
||||
else {
|
||||
utils_1.newJSXIfAttr(jsxElementPath.node, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (block.children.length !== 0) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.else);
|
||||
}
|
||||
block.children.push(jsxElementPath.node);
|
||||
finalReturnElement = block;
|
||||
returnedPaths.push(parentPath);
|
||||
}
|
||||
}
|
||||
else if (t.isArrowFunctionExpression(parentNode)) {
|
||||
//
|
||||
}
|
||||
else if (t.isAssignmentExpression(parentNode)) {
|
||||
if (t.isIdentifier(parentNode.left)) {
|
||||
const name = parentNode.left.name;
|
||||
const bindingNode = bodyScope.getOwnBinding(name).path.node;
|
||||
const block = templates.get(name) || jsx_1.buildBlockElement();
|
||||
if (utils_1.isEmptyDeclarator(bindingNode)) {
|
||||
const ifStatement = parentPath.findParent(p => p.isIfStatement());
|
||||
const blockStatement = parentPath.findParent(p => p.isBlockStatement());
|
||||
if (utils_1.isBlockIfStatement(ifStatement, blockStatement)) {
|
||||
const { test, alternate, consequent } = ifStatement.node;
|
||||
if (alternate === blockStatement.node) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.else);
|
||||
}
|
||||
else if (consequent === blockStatement.node) {
|
||||
const parentIfStatement = ifStatement.findParent(p => p.isIfStatement());
|
||||
if (parentIfStatement && parentIfStatement.get('alternate') === ifStatement) {
|
||||
jsx_1.setJSXAttr(jsxElementPath.node, adapter_1.Adapter.elseif, t.jSXExpressionContainer(test));
|
||||
}
|
||||
else {
|
||||
if (parentIfStatement) {
|
||||
utils_1.newJSXIfAttr(block, parentIfStatement.node.test);
|
||||
}
|
||||
utils_1.newJSXIfAttr(jsxElementPath.node, test);
|
||||
}
|
||||
}
|
||||
block.children.push(jsxElementPath.node);
|
||||
// setTemplate(name, path, templates)
|
||||
name && templates.set(name, block);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw utils_1.codeFrameError(jsxElementPath.node.loc, '请将 JSX 赋值表达式初始化为 null,然后再进行 if 条件表达式赋值。');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!t.isJSXElement(parentNode)) {
|
||||
// throwError(path, '考虑只对 JSX 元素赋值一次。')
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.parseLoopBody = parseLoopBody;
|
||||
//# sourceMappingURL=loop-component.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const eslint_1 = require("./eslint");
|
||||
exports.transformOptions = {};
|
||||
exports.setTransformOptions = (options) => {
|
||||
for (const key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
exports.transformOptions[key] = options[key];
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.buildBabelTransformOptions = () => {
|
||||
return {
|
||||
parserOpts: {
|
||||
sourceType: 'module',
|
||||
plugins: [
|
||||
'classProperties',
|
||||
'jsx',
|
||||
'flow',
|
||||
'flowComment',
|
||||
'trailingFunctionCommas',
|
||||
'asyncFunctions',
|
||||
'exponentiationOperator',
|
||||
'asyncGenerators',
|
||||
'objectRestSpread',
|
||||
'decorators',
|
||||
'dynamicImport'
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
require('babel-plugin-transform-flow-strip-types'),
|
||||
[require('babel-plugin-transform-define').default, exports.transformOptions.env]
|
||||
].concat(process.env.ESLINT === 'false' || exports.transformOptions.isNormal || exports.transformOptions.isTyped ? [] : eslint_1.eslintValidation)
|
||||
.concat((process.env.NODE_ENV === 'test') ? [] : require('babel-plugin-remove-dead-code').default)
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=options.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":";;AACA,qCAA2C;AAgB9B,QAAA,gBAAgB,GAAY,EAAS,CAAA;AAErC,QAAA,mBAAmB,GAAG,CAAC,OAAgB,EAAE,EAAE;IACtD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;QACzB,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;YAC/B,wBAAgB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;SACrC;KACF;AACH,CAAC,CAAA;AAEY,QAAA,0BAA0B,GAA2B,GAAG,EAAE;IACrE,OAAO;QACL,UAAU,EAAE;YACV,UAAU,EAAE,QAAQ;YACpB,OAAO,EAAE;gBACP,iBAAiB;gBACjB,KAAK;gBACL,MAAM;gBACN,aAAa;gBACb,wBAAwB;gBACxB,gBAAgB;gBAChB,wBAAwB;gBACxB,iBAAiB;gBACjB,kBAAkB;gBAClB,YAAY;gBACZ,eAAe;aACP;SACX;QACD,OAAO,EAAE;YACP,OAAO,CAAC,yCAAyC,CAAC;YAClD,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC,OAAO,EAAE,wBAAgB,CAAC,GAAG,CAAC;SACzE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,OAAO,IAAI,wBAAgB,CAAC,QAAQ,IAAI,wBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,yBAAgB,CAAC;aACxH,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC,OAAO,CAAC;KACnG,CAAA;AACH,CAAC,CAAA"}
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const t = require("babel-types");
|
||||
function isString(node) {
|
||||
return t.isLiteral(node) && typeof node.value === 'string';
|
||||
}
|
||||
function buildBinaryExpression(left, right) {
|
||||
return t.binaryExpression('+', left, right);
|
||||
}
|
||||
function templateLiterals(path, state) {
|
||||
let nodes = [];
|
||||
const expressions = path.get('expressions');
|
||||
for (const elem of (path.node.quasis)) {
|
||||
nodes.push(t.stringLiteral(elem.value.cooked));
|
||||
const expr = expressions.shift();
|
||||
if (expr) {
|
||||
// tslint:disable-next-line:no-multi-spaces
|
||||
if (state.opts.spec && !expr.isBaseType('string') && !expr.isBaseType('number')) {
|
||||
nodes.push(t.callExpression(t.identifier('String'), [expr.node]));
|
||||
}
|
||||
else {
|
||||
nodes.push(expr.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
// filter out empty string literals
|
||||
nodes = nodes.filter((n) => !t.isLiteral(n, { value: '' }));
|
||||
// since `+` is left-to-right associative
|
||||
// ensure the first node is a string if first/second isn't
|
||||
if (!isString(nodes[0]) && !isString(nodes[1])) {
|
||||
nodes.unshift(t.stringLiteral(''));
|
||||
}
|
||||
if (nodes.length > 1) {
|
||||
let root = buildBinaryExpression(nodes.shift(), nodes.shift());
|
||||
for (const node of nodes) {
|
||||
root = buildBinaryExpression(root, node);
|
||||
}
|
||||
path.replaceWith(root);
|
||||
}
|
||||
else {
|
||||
path.replaceWith(nodes[0]);
|
||||
}
|
||||
}
|
||||
exports.templateLiterals = templateLiterals;
|
||||
//# sourceMappingURL=plugins.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/plugins.ts"],"names":[],"mappings":";;AAAA,iCAAgC;AAEhC,SAAS,QAAQ,CAAE,IAAI;IACrB,OAAO,CAAC,CAAC,SAAS,CAAC,IAAW,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAA;AACnE,CAAC;AAED,SAAS,qBAAqB,CAAE,IAAI,EAAE,KAAK;IACzC,OAAO,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;AAC7C,CAAC;AACD,SAAgB,gBAAgB,CAAE,IAAI,EAAE,KAAK;IAE3C,IAAI,KAAK,GAAkB,EAAE,CAAA;IAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAE3C,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;QAE9C,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,CAAA;QAChC,IAAI,IAAI,EAAE;YACR,2CAA2C;YAC3C,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAG;gBAChF,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;aAClE;iBAAM;gBACL,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;aACtB;SACF;KACF;IAED,mCAAmC;IACnC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IAE3D,yCAAyC;IACzC,0DAA0D;IAC1D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;KACnC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACpB,IAAI,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QAE9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,IAAI,GAAG,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;SACzC;QAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;KACvB;SAAM;QACL,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;KAC3B;AACH,CAAC;AAxCD,4CAwCC"}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,512 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const t = require("babel-types");
|
||||
const babel_generator_1 = require("babel-generator");
|
||||
const code_frame_1 = require("@babel/code-frame");
|
||||
const constant_1 = require("./constant");
|
||||
const lodash_1 = require("lodash");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const jsx_1 = require("./jsx");
|
||||
const adapter_1 = require("./adapter");
|
||||
const options_1 = require("./options");
|
||||
const template = require('babel-template');
|
||||
exports.incrementId = () => {
|
||||
let id = 0;
|
||||
return () => id++;
|
||||
};
|
||||
// tslint:disable-next-line:no-empty
|
||||
exports.noop = function () { };
|
||||
function getSuperClassCode(path) {
|
||||
const superClass = path.node.superClass;
|
||||
if (t.isIdentifier(superClass)) {
|
||||
const binding = path.scope.getBinding(superClass.name);
|
||||
if (binding && binding.kind === 'module') {
|
||||
const bindingPath = binding.path.parentPath;
|
||||
if (bindingPath.isImportDeclaration()) {
|
||||
const source = bindingPath.node.source;
|
||||
if (source.value === constant_1.TARO_PACKAGE_NAME) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const p = pathResolver(source.value, options_1.transformOptions.sourcePath) + (options_1.transformOptions.isTyped ? '.tsx' : '.js');
|
||||
const code = fs.readFileSync(p, 'utf8');
|
||||
return {
|
||||
code,
|
||||
sourcePath: source.value
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.getSuperClassCode = getSuperClassCode;
|
||||
function isContainStopPropagation(path) {
|
||||
let matched = false;
|
||||
if (path) {
|
||||
path.traverse({
|
||||
Identifier(p) {
|
||||
if (p.node.name === 'stopPropagation' &&
|
||||
p.parentPath.parentPath.isCallExpression()) {
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
exports.isContainStopPropagation = isContainStopPropagation;
|
||||
function decodeUnicode(s) {
|
||||
return unescape(s.replace(/\\(u[0-9a-fA-F]{4})/gm, '%$1'));
|
||||
}
|
||||
exports.decodeUnicode = decodeUnicode;
|
||||
function isVarName(str) {
|
||||
if (typeof str !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (str.trim() !== str) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
new Function(str, 'var ' + str);
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.isVarName = isVarName;
|
||||
function findMethodName(expression) {
|
||||
let methodName;
|
||||
if (t.isIdentifier(expression) ||
|
||||
t.isJSXIdentifier(expression)) {
|
||||
methodName = expression.name;
|
||||
}
|
||||
else if (t.isStringLiteral(expression)) {
|
||||
methodName = expression.value;
|
||||
}
|
||||
else if (t.isMemberExpression(expression) &&
|
||||
t.isIdentifier(expression.property)) {
|
||||
const { code } = babel_generator_1.default(expression);
|
||||
const ids = code.split('.');
|
||||
if (ids[0] === 'this' && ids[1] === 'props' && ids[2]) {
|
||||
methodName = code.replace('this.props.', '');
|
||||
}
|
||||
else {
|
||||
methodName = expression.property.name;
|
||||
}
|
||||
}
|
||||
else if (t.isCallExpression(expression) &&
|
||||
t.isMemberExpression(expression.callee) &&
|
||||
t.isIdentifier(expression.callee.object)) {
|
||||
methodName = expression.callee.object.name;
|
||||
}
|
||||
else if (t.isCallExpression(expression) &&
|
||||
t.isMemberExpression(expression.callee) &&
|
||||
t.isMemberExpression(expression.callee.object) &&
|
||||
t.isIdentifier(expression.callee.property) &&
|
||||
expression.callee.property.name === 'bind' &&
|
||||
t.isIdentifier(expression.callee.object.property)) {
|
||||
methodName = expression.callee.object.property.name;
|
||||
}
|
||||
else {
|
||||
throw codeFrameError(expression.loc, '当 props 为事件时(props name 以 `on` 开头),只能传入一个 this 作用域下的函数。');
|
||||
}
|
||||
return methodName;
|
||||
}
|
||||
exports.findMethodName = findMethodName;
|
||||
function setParentCondition(jsx, expr, array = false) {
|
||||
const conditionExpr = jsx.findParent(p => p.isConditionalExpression());
|
||||
const logicExpr = jsx.findParent(p => p.isLogicalExpression({ operator: '&&' }));
|
||||
if (array) {
|
||||
const ifAttrSet = new Set([
|
||||
adapter_1.Adapter.if,
|
||||
adapter_1.Adapter.else
|
||||
]);
|
||||
const logicalJSX = jsx.findParent(p => p.isJSXElement() && p.node.openingElement.attributes.some(a => ifAttrSet.has(a.name.name)));
|
||||
if (logicalJSX) {
|
||||
const attr = logicalJSX.node.openingElement.attributes.find(a => ifAttrSet.has(a.name.name));
|
||||
if (attr) {
|
||||
if (attr.name.name === adapter_1.Adapter.else) {
|
||||
const prevElement = logicalJSX.getPrevSibling();
|
||||
if (prevElement && prevElement.isJSXElement()) {
|
||||
const attr = prevElement.node.openingElement.attributes.find(a => a.name.name === adapter_1.Adapter.if);
|
||||
if (attr && t.isJSXExpressionContainer(attr.value)) {
|
||||
expr = t.conditionalExpression(reverseBoolean(lodash_1.cloneDeep(attr.value.expression)), expr, t.arrayExpression());
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t.isJSXExpressionContainer(attr.value)) {
|
||||
expr = t.conditionalExpression(lodash_1.cloneDeep(attr.value.expression), expr, t.arrayExpression());
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (conditionExpr && conditionExpr.isConditionalExpression()) {
|
||||
const consequent = conditionExpr.get('consequent');
|
||||
if (consequent === jsx || jsx.findParent(p => p === consequent)) {
|
||||
expr = t.conditionalExpression(lodash_1.cloneDeep(conditionExpr.get('test').node), expr, array ? t.arrayExpression([]) : t.nullLiteral());
|
||||
}
|
||||
}
|
||||
if (logicExpr && logicExpr.isLogicalExpression({ operator: '&&' })) {
|
||||
const consequent = logicExpr.get('right');
|
||||
if (consequent === jsx || jsx.findParent(p => p === consequent)) {
|
||||
expr = t.conditionalExpression(lodash_1.cloneDeep(logicExpr.get('left').node), expr, array ? t.arrayExpression([]) : t.nullLiteral());
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
exports.setParentCondition = setParentCondition;
|
||||
function generateAnonymousState(scope, expression, refIds, isLogical) {
|
||||
let variableName = `anonymousState_${scope.generateUid()}`;
|
||||
let statementParent = expression.getStatementParent();
|
||||
if (!statementParent) {
|
||||
throw codeFrameError(expression.node.loc, '无法生成匿名 State,尝试先把值赋到一个变量上再把变量调换。');
|
||||
}
|
||||
const jsx = isLogical ? expression : expression.findParent(p => p.isJSXElement());
|
||||
const callExpr = jsx.findParent(p => p.isCallExpression() && isArrayMapCallExpression(p));
|
||||
const ifExpr = jsx.findParent(p => p.isIfStatement());
|
||||
const blockStatement = jsx.findParent(p => p.isBlockStatement() && p.parentPath === ifExpr);
|
||||
const expr = setParentCondition(jsx, lodash_1.cloneDeep(expression.node));
|
||||
if (!callExpr) {
|
||||
refIds.add(t.identifier(variableName));
|
||||
statementParent.insertBefore(buildConstVariableDeclaration(variableName, expr));
|
||||
if (blockStatement && blockStatement.isBlockStatement()) {
|
||||
blockStatement.traverse({
|
||||
VariableDeclarator: (p) => {
|
||||
const { id, init } = p.node;
|
||||
if (t.isIdentifier(id) && !id.name.startsWith(constant_1.LOOP_STATE)) {
|
||||
const newId = scope.generateDeclaredUidIdentifier('$' + id.name);
|
||||
refIds.forEach((refId) => {
|
||||
if (refId.name === variableName && !variableName.startsWith('_$')) {
|
||||
refIds.delete(refId);
|
||||
}
|
||||
});
|
||||
variableName = newId.name;
|
||||
refIds.add(t.identifier(variableName));
|
||||
blockStatement.scope.rename(id.name, newId.name);
|
||||
p.parentPath.replaceWith(template('ID = INIT;')({ ID: newId, INIT: init }));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
variableName = `${constant_1.LOOP_STATE}_${callExpr.scope.generateUid()}`;
|
||||
const func = callExpr.node.arguments[0];
|
||||
if (t.isArrowFunctionExpression(func)) {
|
||||
if (!t.isBlockStatement(func.body)) {
|
||||
func.body = t.blockStatement([
|
||||
buildConstVariableDeclaration(variableName, expr),
|
||||
t.returnStatement(func.body)
|
||||
]);
|
||||
}
|
||||
else {
|
||||
if (ifExpr && ifExpr.isIfStatement() && ifExpr.findParent(p => p === callExpr)) {
|
||||
const consequent = ifExpr.get('consequent');
|
||||
const test = ifExpr.get('test');
|
||||
if (consequent.isBlockStatement()) {
|
||||
if (jsx === test || jsx.findParent(p => p === test)) {
|
||||
func.body.body.unshift(buildConstVariableDeclaration(variableName, expr));
|
||||
}
|
||||
else {
|
||||
func.body.body.unshift(t.variableDeclaration('let', [t.variableDeclarator(t.identifier(variableName), t.nullLiteral())]));
|
||||
consequent.node.body.push(t.expressionStatement(t.assignmentExpression('=', t.identifier(variableName), expr)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw codeFrameError(consequent.node, 'if 表达式的结果必须由一个花括号包裹');
|
||||
}
|
||||
}
|
||||
else {
|
||||
func.body.body.splice(func.body.body.length - 1, 0, buildConstVariableDeclaration(variableName, expr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const id = t.identifier(variableName);
|
||||
expression.replaceWith(id);
|
||||
return id;
|
||||
}
|
||||
exports.generateAnonymousState = generateAnonymousState;
|
||||
function isArrayMapCallExpression(callExpression) {
|
||||
return callExpression &&
|
||||
t.isCallExpression(callExpression.node) &&
|
||||
t.isMemberExpression(callExpression.node.callee) &&
|
||||
t.isIdentifier(callExpression.node.callee.property, { name: 'map' });
|
||||
}
|
||||
exports.isArrayMapCallExpression = isArrayMapCallExpression;
|
||||
function buildConstVariableDeclaration(variableName, expresion) {
|
||||
return t.variableDeclaration('const', [
|
||||
t.variableDeclarator(t.identifier(variableName), expresion)
|
||||
]);
|
||||
}
|
||||
exports.buildConstVariableDeclaration = buildConstVariableDeclaration;
|
||||
function setTemplate(name, path, templates) {
|
||||
const parentPath = path.parentPath;
|
||||
const jsxChildren = parentPath.findParent(p => p.isJSXElement());
|
||||
if (name && !jsxChildren) {
|
||||
templates.set(name, path.node);
|
||||
}
|
||||
}
|
||||
exports.setTemplate = setTemplate;
|
||||
function isContainFunction(p) {
|
||||
let bool = false;
|
||||
p.traverse({
|
||||
CallExpression() {
|
||||
bool = true;
|
||||
}
|
||||
});
|
||||
return bool;
|
||||
}
|
||||
exports.isContainFunction = isContainFunction;
|
||||
function slash(input) {
|
||||
const isExtendedLengthPath = /^\\\\\?\\/.test(input);
|
||||
const hasNonAscii = /[^\u0000-\u0080]+/.test(input);
|
||||
const hasChinese = /[^\u4e00-\u9fa5]+/.test(input); // has Chinese characters
|
||||
if (isExtendedLengthPath || (hasNonAscii && !hasChinese)) {
|
||||
return input;
|
||||
}
|
||||
return input.replace(/\\/g, '/');
|
||||
}
|
||||
function pathResolver(source, location) {
|
||||
const extName = path.extname(source);
|
||||
const promotedPath = source;
|
||||
if (!['js', 'tsx'].includes(extName)) {
|
||||
try {
|
||||
const pathExist = fs.existsSync(path.resolve(path.dirname(location), source, 'index.js'));
|
||||
const tsxPathExist = fs.existsSync(path.resolve(path.dirname(location), source, 'index.tsx'));
|
||||
if (pathExist || tsxPathExist) {
|
||||
let p = path.join(promotedPath, 'index');
|
||||
if (!p.startsWith('.')) {
|
||||
p = './' + p;
|
||||
}
|
||||
return slash(p);
|
||||
}
|
||||
return slash(promotedPath);
|
||||
}
|
||||
catch (error) {
|
||||
return slash(promotedPath);
|
||||
}
|
||||
}
|
||||
return slash(promotedPath.split('.').slice(0, -1).join('.'));
|
||||
}
|
||||
exports.pathResolver = pathResolver;
|
||||
function codeFrameError(node, msg) {
|
||||
let errMsg = '';
|
||||
try {
|
||||
errMsg = code_frame_1.codeFrameColumns(exports.setting.sourceCode, node && node.type && node.loc ? node.loc : node, {
|
||||
highlightCode: true
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
errMsg = 'failed to locate source';
|
||||
}
|
||||
return new Error(`${msg}
|
||||
-----
|
||||
${errMsg}`);
|
||||
}
|
||||
exports.codeFrameError = codeFrameError;
|
||||
exports.setting = {
|
||||
sourceCode: ''
|
||||
};
|
||||
function createUUID() {
|
||||
return '$' + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
let r = Math.random() * 16 | 0;
|
||||
let v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
}).replace(/-/g, '').slice(0, 8);
|
||||
}
|
||||
exports.createUUID = createUUID;
|
||||
function createRandomLetters(n) {
|
||||
const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
return Array(n).join().split(',').map(function () { return str.charAt(Math.floor(Math.random() * str.length)); }).join('');
|
||||
}
|
||||
exports.createRandomLetters = createRandomLetters;
|
||||
function isBlockIfStatement(ifStatement, blockStatement) {
|
||||
return ifStatement && blockStatement &&
|
||||
ifStatement.isIfStatement() &&
|
||||
blockStatement.isBlockStatement();
|
||||
}
|
||||
exports.isBlockIfStatement = isBlockIfStatement;
|
||||
function buildCodeFrame(code) {
|
||||
return (loc) => code_frame_1.codeFrameColumns(code, loc);
|
||||
}
|
||||
exports.buildCodeFrame = buildCodeFrame;
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
exports.isNumeric = isNumeric;
|
||||
function buildJSXAttr(name, value) {
|
||||
return t.jSXAttribute(t.jSXIdentifier(name), t.jSXExpressionContainer(value));
|
||||
}
|
||||
exports.buildJSXAttr = buildJSXAttr;
|
||||
function newJSXIfAttr(jsx, value, path) {
|
||||
const element = jsx.openingElement;
|
||||
if (!t.isJSXIdentifier(element.name)) {
|
||||
return;
|
||||
}
|
||||
if (element.name.name === 'Block' || element.name.name === 'block' || !path) {
|
||||
element.attributes.push(buildJSXAttr(adapter_1.Adapter.if, value));
|
||||
}
|
||||
else {
|
||||
const block = jsx_1.buildBlockElement();
|
||||
newJSXIfAttr(block, value);
|
||||
block.children.push(jsx);
|
||||
path.node = block;
|
||||
}
|
||||
}
|
||||
exports.newJSXIfAttr = newJSXIfAttr;
|
||||
function getSlotName(name) {
|
||||
return name.slice(6).toLowerCase();
|
||||
}
|
||||
exports.getSlotName = getSlotName;
|
||||
function isContainJSXElement(path) {
|
||||
let matched = false;
|
||||
path.traverse({
|
||||
JSXElement(p) {
|
||||
matched = true;
|
||||
p.stop();
|
||||
}
|
||||
});
|
||||
return matched;
|
||||
}
|
||||
exports.isContainJSXElement = isContainJSXElement;
|
||||
function hasComplexExpression(path) {
|
||||
let matched = false;
|
||||
if (isContainJSXElement(path)) {
|
||||
return false;
|
||||
}
|
||||
if (path.isObjectExpression()) {
|
||||
return true;
|
||||
}
|
||||
if (path.isTemplateLiteral() || path.isCallExpression()) {
|
||||
return true;
|
||||
}
|
||||
if (path.isArrayExpression()) {
|
||||
const { elements } = path.node;
|
||||
if (elements.some(el => t.isObjectExpression(el) || t.isArrayExpression(el))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
path.traverse({
|
||||
CallExpression: (p) => {
|
||||
matched = true;
|
||||
p.stop();
|
||||
},
|
||||
TemplateLiteral(p) {
|
||||
matched = true;
|
||||
p.stop();
|
||||
},
|
||||
ObjectExpression(p) {
|
||||
matched = true;
|
||||
p.stop();
|
||||
},
|
||||
ArrayExpression(p) {
|
||||
const { elements } = p.node;
|
||||
if (elements.some(el => t.isObjectExpression(el))) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
TaggedTemplateExpression(p) {
|
||||
matched = true;
|
||||
p.stop();
|
||||
},
|
||||
MemberExpression(path) {
|
||||
const jsxElement = path.findParent(p => p.isJSXExpressionContainer());
|
||||
const object = path.get('object');
|
||||
const property = path.get('property');
|
||||
const parentPath = path.parentPath;
|
||||
if (jsxElement &&
|
||||
object.isThisExpression() &&
|
||||
property.isIdentifier({ name: 'state' }) &&
|
||||
parentPath.isMemberExpression() &&
|
||||
parentPath.parentPath.isMemberExpression()) {
|
||||
const sourceCode = parentPath.parentPath.getSource();
|
||||
if (sourceCode.includes('[') && sourceCode.includes(']')) {
|
||||
matched = true;
|
||||
path.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return matched;
|
||||
}
|
||||
exports.hasComplexExpression = hasComplexExpression;
|
||||
function findFirstIdentifierFromMemberExpression(node, member) {
|
||||
let id;
|
||||
let object = node.object;
|
||||
while (true) {
|
||||
if (t.identifier(object) && !t.isMemberExpression(object)) {
|
||||
id = object;
|
||||
if (member) {
|
||||
object = member;
|
||||
}
|
||||
break;
|
||||
}
|
||||
object = object.object;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
exports.findFirstIdentifierFromMemberExpression = findFirstIdentifierFromMemberExpression;
|
||||
function getArgumentName(arg) {
|
||||
if (t.isThisExpression(arg)) {
|
||||
return 'this';
|
||||
}
|
||||
else if (t.isNullLiteral(arg)) {
|
||||
return 'null';
|
||||
}
|
||||
else if (t.isStringLiteral(arg) || t.isNumericLiteral(arg)) {
|
||||
return arg.value;
|
||||
}
|
||||
else if (t.isIdentifier(arg)) {
|
||||
return arg.name;
|
||||
}
|
||||
else {
|
||||
return babel_generator_1.default(arg).code;
|
||||
}
|
||||
throw new Error(`bind 不支持传入该参数: ${arg}`);
|
||||
}
|
||||
exports.getArgumentName = getArgumentName;
|
||||
function isAllLiteral(...args) {
|
||||
return args.every(p => t.isLiteral(p));
|
||||
}
|
||||
exports.isAllLiteral = isAllLiteral;
|
||||
function reverseBoolean(expression) {
|
||||
return t.unaryExpression('!', expression);
|
||||
}
|
||||
exports.reverseBoolean = reverseBoolean;
|
||||
function isEmptyDeclarator(node) {
|
||||
if (t.isVariableDeclarator(node) &&
|
||||
(node.init === null ||
|
||||
t.isNullLiteral(node.init))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.isEmptyDeclarator = isEmptyDeclarator;
|
||||
function toLetters(num) {
|
||||
let mod = num % 26;
|
||||
let pow = num / 26 | 0;
|
||||
let out = mod ? String.fromCharCode(64 + mod) : (--pow, 'Z');
|
||||
const letter = pow ? toLetters(pow) + out : out;
|
||||
return letter.toLowerCase();
|
||||
}
|
||||
exports.toLetters = toLetters;
|
||||
function findIdentifierFromStatement(statement) {
|
||||
if (t.isVariableDeclaration(statement)) {
|
||||
const declarator = statement.declarations.find(s => t.isIdentifier(s.id));
|
||||
if (declarator && t.isIdentifier(declarator.id)) {
|
||||
return declarator.id.name;
|
||||
}
|
||||
}
|
||||
return '__return';
|
||||
}
|
||||
exports.findIdentifierFromStatement = findIdentifierFromStatement;
|
||||
//# sourceMappingURL=utils.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,74 @@
|
|||
/* mp-jsx v0.1.0
|
||||
base on taro-transformer-wx v1.2.22
|
||||
https://github.com/NervJS/taro/tree/master/packages/taro-transformer-wx
|
||||
*/
|
||||
const jsx2wxml = require('../jsx2wxml')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
|
||||
function buildComponent(code) {
|
||||
return `
|
||||
class WeElement {
|
||||
render () {
|
||||
return ${code}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
const baseOptions = {
|
||||
isRoot: false,
|
||||
isApp: false,
|
||||
sourcePath: __dirname,
|
||||
outputPath: __dirname,
|
||||
code: '',
|
||||
isTyped: false
|
||||
}
|
||||
|
||||
let { template } = jsx2wxml.default({
|
||||
...baseOptions,
|
||||
code: buildComponent(fs.readFileSync(path.join(__dirname, "./test.jsx"), 'utf8'))
|
||||
})
|
||||
|
||||
|
||||
console.log(template ===
|
||||
`<block>
|
||||
<view>show</view>
|
||||
</block>`)
|
||||
|
||||
template = jsx2wxml.default({
|
||||
...baseOptions,
|
||||
code: buildComponent(fs.readFileSync(path.join(__dirname, "./test.1.jsx"), 'utf8'))
|
||||
}).template
|
||||
|
||||
|
||||
console.log(template ===
|
||||
`<block>
|
||||
<block>
|
||||
<block wx:if="{{bb}}">
|
||||
<view>show</view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<view>hide</view>
|
||||
</block>
|
||||
</block>
|
||||
</block>`)
|
||||
|
||||
|
||||
|
||||
template = jsx2wxml.default({
|
||||
...baseOptions,
|
||||
code: buildComponent(fs.readFileSync(path.join(__dirname, "./test.2.jsx"), 'utf8'))
|
||||
}).template
|
||||
|
||||
|
||||
console.log(template ===
|
||||
`<block>
|
||||
<view>
|
||||
<view bindtap="onTap" wx:for="{{array}}" wx:for-item="item" wx:for-index="_anonIdx"><text>{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>`)
|
||||
|
|
@ -0,0 +1 @@
|
|||
bb?<view>show</view>:<view>hide</view>
|
|
@ -0,0 +1,7 @@
|
|||
<view>
|
||||
{array.map(item => (
|
||||
<view onTap={this.onTap}>
|
||||
<text>{item.name}</text>
|
||||
</view>
|
||||
))}
|
||||
</view>
|
|
@ -0,0 +1 @@
|
|||
<view>show</view>
|
|
@ -3,9 +3,24 @@
|
|||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"tsc": "./node_modules/typescript/bin/tsc",
|
||||
"compile": "tsc"
|
||||
"compile": "tsc",
|
||||
"start": "gulp",
|
||||
"_test": "node _scripts/test/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^3.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@tarojs/transformer-wx": "^1.2.22",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-generator": "^6.26.1",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-tap": "^1.0.1",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue