You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _react() {
const data = _interopRequireDefault(require("react"));
_react = function _react() {
return data;
};
return data;
}
function _assert() {
const data = _interopRequireDefault(require("assert"));
_assert = function _assert() {
return data;
};
return data;
}
function _umi() {
const data = require("umi");
_umi = function _umi() {
return data;
};
return data;
}
function t() {
const data = _interopRequireWildcard(require("@babel/types"));
t = function t() {
return data;
};
return data;
}
var _util = require("../util");
var _constants = require("../constants");
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const winPath = _umi().utils.winPath;
var _default = () => {
function buildGUmiUIFlag(opts) {
const index = opts.index,
filename = opts.filename,
jsx = opts.jsx,
inline = opts.inline,
content = opts.content;
if (jsx) {
const attrs = [t().jsxAttribute(t().jsxIdentifier('filename'), t().stringLiteral(`${filename}`)), t().jsxAttribute(t().jsxIdentifier('index'), t().stringLiteral(`${index}`))];
if (inline) {
attrs.push(t().jsxAttribute(t().jsxIdentifier('inline'), t().stringLiteral('true')));
}
return t().jsxElement(t().jsxOpeningElement(t().jsxIdentifier('GUmiUIFlag'), attrs), t().jsxClosingElement(t().jsxIdentifier('GUmiUIFlag')), content ? [t().jsxText(content)] : [], false);
}
const attrs = [t().objectProperty(t().identifier('filename'), t().stringLiteral(`${filename}`)), t().objectProperty(t().identifier('index'), t().stringLiteral(`${index}`))];
if (inline) {
attrs.push(t().objectProperty(t().identifier('inline'), t().stringLiteral('true')));
}
return t().callExpression(t().memberExpression(t().identifier('React'), t().identifier('createElement')), [t().identifier('GUmiUIFlag'), t().objectExpression(attrs), ...(content ? [t().stringLiteral(content)] : [])]);
}
function addFlagToIndex(nodes, i, {
index,
filename,
jsx
}) {
nodes.splice(i, 0, buildGUmiUIFlag({
index,
filename,
jsx
}));
}
function addUmiUIFlag(node, {
filename,
replace
}) {
if ((0, _util.isJSXElement)(node)) {
if ((0, _util.isChildFunc)(node)) {
return;
}
if ((0, _util.haveChildren)(node)) {
if (t().isJSXElement(node) || t().isJSXFragment(node)) {
let index = node.children.filter(n => (0, _util.isJSXElement)(n)).length;
let i = node.children.length - 1;
while (i >= 0) {
const child = node.children[i];
if ((0, _util.isJSXElement)(child) || i === 0) {
addFlagToIndex(node.children, i === 0 ? i : i + 1, {
index,
filename,
jsx: true
});
index -= 1;
}
i -= 1;
}
} else {
const args = node.arguments;
let index = args.filter(n => (0, _util.isReactCreateElement)(n)).length;
let i = args.length - 1;
while (i >= 1) {
const arg = args[i];
if ((0, _util.isReactCreateElement)(arg) || i === 1) {
addFlagToIndex(args, i + 1, {
index,
filename,
jsx: false
});
index -= 1;
}
i -= 1;
}
}
} else {
// root 节点没有 children则在外面套一层
replace(t().isJSXElement(node) ? t().jsxFragment(t().jsxOpeningFragment(), t().jsxClosingFragment(), [buildGUmiUIFlag({
index: 0,
filename,
jsx: true
}), node, buildGUmiUIFlag({
index: 1,
filename,
jsx: true
})]) : t().callExpression(t().memberExpression(t().identifier('React'), t().identifier('createElement')), [t().memberExpression(t().identifier('React'), t().identifier('Fragment')), t().nullLiteral(), buildGUmiUIFlag({
index: 0,
filename,
jsx: false
}), node, buildGUmiUIFlag({
index: 1,
filename,
jsx: false
})]));
}
} else {// throw new Error(`Add umi ui flag failed, unsupported node type ${node.type}.`);
}
}
function isInBlackList(node, path) {
if (t().isJSXElement(node)) {
const name = node.openingElement.name.name;
if (path.scope.hasBinding(name)) {
const p = path.scope.getBinding(name).path;
const source = p.parentPath.node.source; // 只处理 import 的声明
if (!t().isImportDeclaration(p.parentPath.node)) return;
if (['react-document-title', 'react-intl'].includes(source.value)) {
return true;
} // antd 和 @alipay/tech-ui 里除部分用于布局的组件之外,其他组件作为根组件不会插入编辑区
if ((source.value === 'antd' || source.value === '@alipay/bigfish/antd') && t().isImportSpecifier(p.node) && t().isIdentifier(p.node.imported) && !['Card', 'Grid', 'Layout'].includes(p.node.imported.name)) {
return true;
}
if (source.value === '@alipay/tech-ui' && t().isImportSpecifier(p.node) && t().isIdentifier(p.node.imported) && !['PageContainer'].includes(p.node.imported.name)) {
return true;
}
if (t().isImportSpecifier(p.node) && t().isIdentifier(p.node.imported) && ['Switch', 'Route', 'Router', 'StaticRouter', 'Redirect', 'Link', 'NavLink', 'HashRouter', 'BrowserRouter'].includes(p.node.imported.name)) {
return true;
}
}
}
}
let layoutIndexByFilename = {};
/**
* 检查是否走 Babel目前只针对 /pages/ 或 /page/ 目录下的页面
* 其它不作为添加的入口
* @param filename 路径名
*/
const checkPathFilename = filename => {
if (winPath(filename).indexOf('pages/') > -1 || winPath(filename).indexOf('page/') > -1) {
return true;
}
return false;
};
return {
visitor: {
Program: {
enter(path, state) {
// hmr 时会重复编译相同文件
layoutIndexByFilename = {};
const filename = state.filename,
_state$opts = state.opts,
opts = _state$opts === void 0 ? {} : _state$opts;
(0, _assert().default)(opts.doTransform, 'opts.doTransform must supplied');
if (!opts.doTransform(filename)) return;
const node = path.node;
let d = (0, _util.findExportDefaultDeclaration)(node); // Support hoc
while (t().isCallExpression(d)) {
// eslint-disable-next-line
d = d.arguments[0];
}
d = (0, _util.getIdentifierDeclaration)(d, path); // Support hoc again
while (t().isCallExpression(d)) {
// eslint-disable-next-line
d = d.arguments[0];
}
const ret = (0, _util.getReturnNode)(d, path);
if (ret) {
const retNode = ret.node,
replace = ret.replace;
if (retNode && !isInBlackList(retNode, path) && checkPathFilename(filename)) {
addUmiUIFlag(retNode, {
filename: winPath(filename),
replace
});
}
}
}
},
CallExpression(path, state) {
const filename = state.filename,
_state$opts2 = state.opts,
opts = _state$opts2 === void 0 ? {} : _state$opts2; // 不限于路由组件,因为添加进来的区块不是路由组件
// assert(opts.doTransform, 'opts.doTransform must supplied');
// if (!opts.doTransform(filename)) return;
const node = path.node;
const callee = node.callee,
args = node.arguments; // e.g.
// _react.default.createElement("div", null, "INSERT_BLOCK_PLACEHOLDER")
if (t().isStringLiteral(args[2]) && args[2].value.startsWith(_constants.INSERT_BLOCK_PLACEHOLDER) && t().isMemberExpression(callee) && t().isIdentifier(callee.property, {
name: 'createElement'
})) {
if (!layoutIndexByFilename[filename]) {
layoutIndexByFilename[filename] = 0;
}
const index = layoutIndexByFilename[filename];
let content = null;
if (args[2].value.startsWith(`${_constants.INSERT_BLOCK_PLACEHOLDER}:`)) {
content = args[2].value.replace(`${_constants.INSERT_BLOCK_PLACEHOLDER}:`, '');
}
args[2] = buildGUmiUIFlag({
index: `${_constants.BLOCK_LAYOUT_PREFIX}${index}`,
filename: winPath(filename),
jsx: false,
inline: true,
content
});
layoutIndexByFilename[filename] += 1;
} // _react.default.createElement(_umi.UmiUIFlag, null)
if (t().isMemberExpression(callee) && t().isIdentifier(callee.property, {
name: 'createElement'
}) && t().isIdentifier(args[0]) && args[0].name === _constants.UMI_UI_FLAG_PLACEHOLDER) {
if (!layoutIndexByFilename[filename]) {
layoutIndexByFilename[filename] = 0;
}
const index = layoutIndexByFilename[filename];
const content = null;
let inline = false;
if (t().isObjectExpression(args[1]) && args[1].properties.some(property => {
var _property$key, _property$value;
return t().isProperty(property) && ((_property$key = property.key) === null || _property$key === void 0 ? void 0 : _property$key.name) === 'inline' && ((_property$value = property.value) === null || _property$value === void 0 ? void 0 : _property$value.value) === true;
})) {
inline = true;
}
path.replaceWith(buildGUmiUIFlag({
index: `${_constants.BLOCK_LAYOUT_PREFIX}${index}`,
filename: winPath(filename),
jsx: false,
inline,
content
}));
layoutIndexByFilename[filename] += 1;
}
}
}
};
};
exports.default = _default;