"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.applyCodemod = void 0; const apply_visual_control_1 = require("./apply-visual-control"); const applyCodemod = ({ file, codeMod, }) => { const changesMade = []; if (codeMod.type === 'apply-visual-control') { return (0, apply_visual_control_1.applyVisualControl)({ file, transformation: codeMod, changesMade }); } const body = file.program.body.map((node) => { return mapAll(node, codeMod, changesMade); }); return { newAst: { ...file, program: { ...file.program, body, }, }, changesMade, }; }; exports.applyCodemod = applyCodemod; const mapAll = (node, transformation, changesMade) => { if (isRecognizedType(node)) { return mapRecognizedType(node, transformation, changesMade); } return node; }; const isRecognizedType = (t) => { return (t.type === 'ArrowFunctionExpression' || t.type === 'FunctionExpression' || t.type === 'JSXFragment' || t.type === 'JSXElement' || t.type === 'BlockStatement' || t.type === 'ReturnStatement' || t.type === 'VariableDeclaration' || t.type === 'FunctionDeclaration' || t.type === 'ExportNamedDeclaration' || t.type === 'ExportDefaultDeclaration'); }; const mapVariableDeclarator = (variableDeclarator, transformation, changesMade) => { return { ...variableDeclarator, init: variableDeclarator.init ? mapAll(variableDeclarator.init, transformation, changesMade) : variableDeclarator.init, }; }; const mapBlockStatement = (blockStatement, transformation, changesMade) => { return { ...blockStatement, body: blockStatement.body.map((a) => { return mapAll(a, transformation, changesMade); }), }; }; const mapReturnStatement = (statement, transformation, changesMade) => { if (!statement.argument) { return statement; } return { ...statement, argument: mapAll(statement.argument, transformation, changesMade), }; }; const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade) => { return { ...jsxFragment, children: jsxFragment.children .map((c) => { if (c.type !== 'JSXElement') { return c; } return mapJsxChild(c, transformation, changesMade); }) .flat(1), }; }; const mapJsxChild = (c, transformation, changesMade) => { const compId = getCompositionIdFromJSXElement(c); if (transformation === null) { return [c]; } if (transformation.type === 'duplicate-composition' && compId === transformation.idToDuplicate) { return [ c, changeComposition({ jsxElement: c, newCompositionId: transformation.newId, newCompositionFps: transformation.newFps, newCompositionDurationInFrames: transformation.newDurationInFrames, newCompositionHeight: transformation.newHeight, newCompositionWidth: transformation.newWidth, newTagToUse: transformation.tag, changesMade, }), ]; } if (transformation.type === 'rename-composition' && compId === transformation.idToRename) { return [ changeComposition({ jsxElement: c, newCompositionId: transformation.newId, newCompositionFps: null, newCompositionDurationInFrames: null, newCompositionHeight: null, newCompositionWidth: null, changesMade, newTagToUse: null, }), ]; } if (transformation.type === 'delete-composition' && compId === transformation.idToDelete) { changesMade.push({ description: 'Deleted composition', }); return []; } return [mapAll(c, transformation, changesMade)]; }; const mapRecognizedType = (expression, transformation, changesMade) => { if (expression.type === 'JSXFragment' || expression.type === 'JSXElement') { return mapJsxElementOrFragment(expression, transformation, changesMade); } if (expression.type === 'ArrowFunctionExpression' || expression.type === 'FunctionExpression') { return { ...expression, body: mapAll(expression.body, transformation, changesMade), }; } if (expression.type === 'VariableDeclaration') { const declarations = expression.declarations.map((d) => { return mapVariableDeclarator(d, transformation, changesMade); }); return { ...expression, declarations }; } if (expression.type === 'FunctionDeclaration') { return { ...expression, body: mapBlockStatement(expression.body, transformation, changesMade), }; } if (expression.type === 'ExportNamedDeclaration' || expression.type === 'ExportDefaultDeclaration') { if (!expression.declaration) { return expression; } return { ...expression, declaration: mapAll(expression.declaration, transformation, changesMade), }; } if (expression.type === 'ReturnStatement') { return mapReturnStatement(expression, transformation, changesMade); } if (expression.type === 'BlockStatement') { return mapBlockStatement(expression, transformation, changesMade); } return expression; }; const getCompositionIdFromJSXElement = (jsxElement) => { if (jsxElement.type !== 'JSXElement') { return null; } const { openingElement } = jsxElement; const { name } = openingElement; if (name.type !== 'JSXIdentifier') { return null; } if (name.name !== 'Composition' && name.name !== 'Still') { return null; } const id = openingElement.attributes .map((attribute) => { if (attribute.type === 'JSXSpreadAttribute') { return null; } if (attribute.name.type === 'JSXNamespacedName') { return null; } if (attribute.name.name !== 'id') { return null; } if (!attribute.value) { return null; } if (attribute.value.type === 'StringLiteral') { return attribute.value.value; } if (attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'StringLiteral') { return attribute.value.expression.value; } return null; }) .filter(Boolean); return id[0]; }; const changeComposition = ({ jsxElement, newCompositionId, newCompositionFps, newCompositionDurationInFrames, newCompositionHeight, newCompositionWidth, changesMade, newTagToUse, }) => { const { openingElement } = jsxElement; const { name } = openingElement; if (name.type !== 'JSXIdentifier') { return jsxElement; } if (name.name !== 'Composition' && name.name !== 'Still') { return jsxElement; } const attributes = openingElement.attributes .map((attribute) => { if (attribute.type === 'JSXSpreadAttribute') { return attribute; } if (attribute.name.type === 'JSXNamespacedName') { return attribute; } if (attribute.name.name === 'fps' && newTagToUse === 'Still') { changesMade.push({ description: 'Removed fps attribute' }); return null; } if (attribute.name.name === 'durationInFrames' && newTagToUse === 'Still') { changesMade.push({ description: 'Removed durationInFrames' }); return null; } // id="one" if (attribute.name.name === 'id' && attribute.value && attribute.value.type === 'StringLiteral') { changesMade.push({ description: 'Replaced composition id', }); return { ...attribute, value: { ...attribute.value, value: newCompositionId }, }; } // id={"one"} if (attribute.name.name === 'id' && attribute.value && attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'StringLiteral') { changesMade.push({ description: 'Replaced composition id', }); return { ...attribute, value: { ...attribute.value, expression: { ...attribute.value.expression, value: newCompositionId, }, }, }; } if (attribute.name.name === 'fps' && attribute.value && attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'NumericLiteral' && newCompositionFps !== null) { changesMade.push({ description: 'Replaced FPS', }); return { ...attribute, value: { ...attribute.value, expression: { ...attribute.value.expression, value: newCompositionFps, }, }, }; } if (attribute.name.name === 'durationInFrames' && attribute.value && attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'NumericLiteral' && newCompositionDurationInFrames !== null) { changesMade.push({ description: 'Replaced durationInFrames', }); return { ...attribute, value: { ...attribute.value, expression: { ...attribute.value.expression, value: newCompositionDurationInFrames, }, }, }; } if (attribute.name.name === 'width' && attribute.value && attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'NumericLiteral' && newCompositionWidth !== null) { changesMade.push({ description: 'Replaced width', }); return { ...attribute, value: { ...attribute.value, expression: { ...attribute.value.expression, value: newCompositionWidth, }, }, }; } if (attribute.name.name === 'height' && attribute.value && attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'NumericLiteral' && newCompositionHeight !== null) { changesMade.push({ description: 'Replaced height', }); return { ...attribute, value: { ...attribute.value, expression: { ...attribute.value.expression, value: newCompositionHeight, }, }, }; } return attribute; }) .filter(Boolean); const newName = newTagToUse !== null && newTagToUse !== void 0 ? newTagToUse : name.name; if (newName !== name.name) { changesMade.push({ description: `Changed tag`, }); } return { ...jsxElement, openingElement: { ...jsxElement.openingElement, name: { ...name, name: newName, }, attributes, }, }; };