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