UNPKG

zelda-ast

Version:

zelda static analysis based on javascript ast.

94 lines (81 loc) 3.02 kB
import { renderTemplate, writeFile, writeCSSFile, readFile, removeFile, } from './utils'; import { getExpression } from '../utils/index'; import { existsSync } from 'fs'; import { join, extname } from 'path'; import assert from 'assert'; import j from 'jscodeshift'; export function create(payload) { assert(payload.componentName, 'api/routeComponents/create: payload should have componentName'); const source = renderTemplate('routeComponents.create', payload); const filePath = join(payload.sourcePath, payload.filePath); assert(!existsSync(filePath), 'api/routeComponents/create: file exists'); writeFile(filePath, source); if (payload.css) { let cssFilePath = filePath; const en = extname(filePath); if (en) { cssFilePath = filePath.slice(0, filePath.lastIndexOf(en)); } cssFilePath = cssFilePath + '.css'; writeCSSFile(cssFilePath, `\r\n.root {\r\n\r\n}\r\n`); } } export function remove(payload) { const filePath = join(payload.sourcePath, payload.filePath); removeFile(filePath); } export function update(payload) { assert(payload.source, 'api/routeComponents/update: payload should have source'); const filePath = join(payload.sourcePath, payload.filePath); writeFile(filePath, payload.source); } function addDispatchButton(path, dispatchAction, callback) { let once = false; const jsxElements = j(path).find(j.JSXElement, (node) => { if (once) { return false; } // return false is used to prevent nest traverse once = true; return node; }); const rootElement = jsxElements.at(0); rootElement.__paths[0].value.children.unshift( getExpression(`\r\n<button onClick={() => { ${callback}; }}>click to dispatch ${dispatchAction}</button>\n`) ); } export function addDispatch(payload) { assert(payload.actionType, 'api/routeComponents/addDispatch: payload should have actionType'); const filePath = join(payload.sourcePath, payload.filePath); const source = readFile(filePath); const root = j(source); root.findRouteComponents().forEach(path => { if (path.node.type === 'ClassDeclaration') { // add method const methodName = `["${payload.actionType}"]`; const callMethod = `this${methodName}()`; const renderMethod = j(path).find(j.MethodDefinition, { key: { type: 'Identifier', name: 'render', }, }).at(0); renderMethod.insertBefore( j.methodDefinition( 'method', j.identifier(methodName), getExpression(`\nfunction() {\n this.props.dispatch({ type: '${payload.actionType}', payload: {} });\n}`) ) ); // add button & callback to render addDispatchButton(path, payload.actionType, callMethod); } else if(path.node.type === 'FunctionDeclaration') { const callFunction = `props.dispatch({ type: '${payload.actionType}', payload: {} })`; addDispatchButton(path, payload.actionType, callFunction); } }); writeFile(filePath, root.toSource()); }