UNPKG

zelda-ast

Version:

zelda static analysis based on javascript ast.

127 lines (98 loc) 3.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _jscodeshift = require('jscodeshift'); var _jscodeshift2 = _interopRequireDefault(_jscodeshift); var _Collection = require('jscodeshift/src/Collection'); var _Collection2 = _interopRequireDefault(_Collection); var _lodash = require('lodash.once'); var _lodash2 = _interopRequireDefault(_lodash); var _assert = require('assert'); var _assert2 = _interopRequireDefault(_assert); var _Helper = require('./Helper'); var _Helper2 = _interopRequireDefault(_Helper); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } _Helper2.default.register(); const methods = { findRouters() { if (!this.hasModule('dva/router')) return _Collection2.default.fromPaths([], this); return this.find(_jscodeshift2.default.JSXElement, { openingElement: { name: { type: 'JSXIdentifier', name: 'Router' } } }); }, // TODO: support config router with JavaScript Object getRouterInfo() { const routeByIds = {}; const ROUTER_COMPONENTS = ['Router', 'Route', 'Switch', 'Redirect', 'IndexRedirect', 'IndexRoute']; function parse(node, parentPath = '', parentId, parentDepth = -1) { (0, _assert2.default)(node.type === 'JSXElement', `getRouterTree: node should be JSXElement, but got ${node.type}`); const name = node.openingElement.name.name; (0, _assert2.default)(ROUTER_COMPONENTS.indexOf(name) > -1, `getRouterTree: component should be one of ${ROUTER_COMPONENTS.join(', ')}`); const ret = { type: name }; ret.depth = parentDepth + 1; ret.attributes = (0, _jscodeshift2.default)(node.openingElement).find(_jscodeshift2.default.JSXAttribute).simpleMap(path => { const node = path.node; return { name: node.name.name, value: getAttributeValue(node.value) }; }).reduce((memo, { name, value }) => { memo[name] = value; return memo; }, {}); const path = ret.attributes.path; if (path) { ret.absolutePath = path.charAt(0) === '/' ? path : `${parentPath}/${path}`; } if (ret.absolutePath) { ret.id = `${ret.type}-${ret.absolutePath}`; } else if (parentId) { ret.id = `${ret.type}-parentId_${parentId}`; } else { ret.id = `${ret.type}-root`; } // 有些特殊情况 id 会重复(同样的父子路由,出现在多处,可能父亲的父亲不一样) if (routeByIds[ret.id]) { ret.id = `${ret.id}_${Math.random()}`; } if (node.children) { ret.children = node.children.filter(node => node.type === 'JSXElement').map(node => parse(node, ret.attributes.path, ret.id, ret.depth)); } routeByIds[ret.id] = ret; return { id: ret.id, children: ret.children }; } function getAttributeValue(node) { if (node) { if (node.type === 'Literal') { return node.value; } else if (node.expression.type === 'Identifier') { return node.expression.name; } else if (node.type === 'JSXExpressionContainer') { return (0, _jscodeshift2.default)(node.expression).toSource(); } throw new Error(`getRouterTree: unsupported attribute type`); } return null; } return this.simpleMap(path => ({ tree: parse(path.node), routeByIds })); } }; function register(jscodeshift = _jscodeshift2.default) { jscodeshift.registerMethods(methods); } exports.default = { register: (0, _lodash2.default)(register) }; module.exports = exports['default'];