UNPKG

jest-preset-angular

Version:

Jest preset configuration for Angular projects

207 lines (206 loc) 9.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.replaceResources = replaceResources; const typescript_1 = __importDefault(require("typescript")); const constants_1 = require("../constants"); const isAfterVersion = (targetMajor, targetMinor) => { const [major, minor] = typescript_1.default.versionMajorMinor.split('.').map((part) => parseInt(part)); if (major < targetMajor) { return false; } else if (major > targetMajor) { return true; } else { return minor >= targetMinor; } }; const IS_TS_48 = isAfterVersion(4, 8); const IS_AFTER_TS_50 = isAfterVersion(5, 0); const shouldTransform = (fileName) => !fileName.endsWith('.ngfactory.ts') && !fileName.endsWith('.ngstyle.ts'); function replaceResources(program) { return (context) => { const typeChecker = program.getTypeChecker(); const resourceImportDeclarations = []; const moduleKind = context.getCompilerOptions().module; const nodeFactory = context.factory; const visitNode = (node) => { if (typescript_1.default.isClassDeclaration(node)) { return visitClassDeclaration(nodeFactory, typeChecker, node, resourceImportDeclarations, moduleKind); } return typescript_1.default.visitEachChild(node, visitNode, context); }; return (sourceFile) => { if (!shouldTransform(sourceFile.fileName)) { return sourceFile; } const updatedSourceFile = typescript_1.default.visitNode(sourceFile, visitNode); if (resourceImportDeclarations.length) { return nodeFactory.updateSourceFile(updatedSourceFile, typescript_1.default.setTextRange(nodeFactory.createNodeArray([...resourceImportDeclarations, ...updatedSourceFile.statements]), updatedSourceFile.statements)); } return updatedSourceFile; }; }; } function visitClassDeclaration(nodeFactory, typeChecker, node, resourceImportDeclarations, moduleKind) { var _a, _b, _c; let decorators; let modifiers; if (IS_TS_48) { (_a = node.modifiers) === null || _a === void 0 ? void 0 : _a.forEach((modifier) => { if (typescript_1.default.isDecorator(modifier)) { decorators !== null && decorators !== void 0 ? decorators : (decorators = []); decorators.push(modifier); } else { modifiers = modifiers !== null && modifiers !== void 0 ? modifiers : (modifiers = []); modifiers.push(modifier); } }); } else { decorators = [...((_b = typescript_1.default.getDecorators(node)) !== null && _b !== void 0 ? _b : [])]; modifiers = [...((_c = typescript_1.default.getModifiers(node)) !== null && _c !== void 0 ? _c : [])]; } if (!decorators || !decorators.length) { return node; } decorators = decorators.map((current) => visitDecorator(nodeFactory, current, typeChecker, resourceImportDeclarations, moduleKind)); return IS_TS_48 ? nodeFactory.updateClassDeclaration(node, [...decorators, ...(modifiers !== null && modifiers !== void 0 ? modifiers : [])], node.name, node.typeParameters, node.heritageClauses, node.members) : nodeFactory.updateClassDeclaration(node, decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members); } function visitDecorator(nodeFactory, node, typeChecker, resourceImportDeclarations, moduleKind) { if (!isComponentDecorator(node, typeChecker)) { return node; } if (!typescript_1.default.isCallExpression(node.expression)) { return node; } const decoratorFactory = node.expression; const args = decoratorFactory.arguments; if (args.length !== 1 || !typescript_1.default.isObjectLiteralExpression(args[0])) { return node; } const objectExpression = args[0]; const styleReplacements = []; let properties = typescript_1.default.visitNodes(objectExpression.properties, (objExpressionNode) => typescript_1.default.isObjectLiteralElementLike(objExpressionNode) ? visitComponentMetadata(nodeFactory, objExpressionNode, resourceImportDeclarations, moduleKind) : objExpressionNode); if (styleReplacements.length) { const styleProperty = nodeFactory.createPropertyAssignment(nodeFactory.createIdentifier(constants_1.STYLES), nodeFactory.createArrayLiteralExpression(styleReplacements)); properties = nodeFactory.createNodeArray([...properties, styleProperty]); } return nodeFactory.updateDecorator(node, nodeFactory.updateCallExpression(decoratorFactory, decoratorFactory.expression, decoratorFactory.typeArguments, [ nodeFactory.updateObjectLiteralExpression(objectExpression, properties), ])); } function visitComponentMetadata(nodeFactory, node, resourceImportDeclarations, moduleKind) { if (!typescript_1.default.isPropertyAssignment(node) || typescript_1.default.isComputedPropertyName(node.name)) { return node; } const name = node.name.text; switch (name) { case 'moduleId': return undefined; case constants_1.TEMPLATE_URL: const url = getResourceUrl(node.initializer); if (!url) { return node; } const importName = createResourceImport(nodeFactory, url, resourceImportDeclarations, moduleKind); if (!importName) { return node; } return nodeFactory.updatePropertyAssignment(node, nodeFactory.createIdentifier(constants_1.TEMPLATE), importName); case constants_1.STYLES: if (!typescript_1.default.isArrayLiteralExpression(node.initializer) && !typescript_1.default.isStringLiteralLike(node.initializer)) { return node; } return undefined; case constants_1.STYLE_URLS: if (!typescript_1.default.isArrayLiteralExpression(node.initializer)) { return node; } return undefined; case constants_1.STYLE_URL: if (!typescript_1.default.isStringLiteralLike(node.initializer)) { return node; } return undefined; default: return node; } } function getResourceUrl(node) { if (!typescript_1.default.isStringLiteral(node) && !typescript_1.default.isNoSubstitutionTemplateLiteral(node)) { return null; } return `${/^\.?\.\//.test(node.text) ? '' : './'}${node.text}`; } function isComponentDecorator(node, typeChecker) { if (!typescript_1.default.isDecorator(node)) { return false; } const origin = getDecoratorOrigin(node, typeChecker); return !!(origin && origin.module === '@angular/core' && origin.name === constants_1.COMPONENT); } function createResourceImport(nodeFactory, url, resourceImportDeclarations, moduleKind = typescript_1.default.ModuleKind.ES2015) { const urlLiteral = nodeFactory.createStringLiteral(url); if (moduleKind < typescript_1.default.ModuleKind.ES2015) { return nodeFactory.createCallExpression(nodeFactory.createIdentifier(constants_1.REQUIRE), [], [urlLiteral]); } else { const importName = nodeFactory.createIdentifier(`__NG_CLI_RESOURCE__${resourceImportDeclarations.length}`); let importDeclaration; if (IS_AFTER_TS_50) { importDeclaration = nodeFactory.createImportDeclaration(undefined, nodeFactory.createImportClause(false, importName, undefined), urlLiteral); } else { importDeclaration = nodeFactory.createImportDeclaration(undefined, undefined, nodeFactory.createImportClause(false, importName, undefined), urlLiteral); } resourceImportDeclarations.push(importDeclaration); return importName; } } function getDecoratorOrigin(decorator, typeChecker) { if (!typescript_1.default.isCallExpression(decorator.expression)) { return null; } let identifier; let name = ''; if (typescript_1.default.isPropertyAccessExpression(decorator.expression.expression)) { identifier = decorator.expression.expression.expression; name = decorator.expression.expression.name.text; } else if (typescript_1.default.isIdentifier(decorator.expression.expression)) { identifier = decorator.expression.expression; } else { return null; } const symbol = typeChecker.getSymbolAtLocation(identifier); if (symbol && symbol.declarations && symbol.declarations.length > 0) { const declaration = symbol.declarations[0]; let module; if (typescript_1.default.isImportSpecifier(declaration)) { name = (declaration.propertyName || declaration.name).text; module = declaration.parent.parent.parent.moduleSpecifier.text; } else if (typescript_1.default.isNamespaceImport(declaration)) { module = declaration.parent.parent.moduleSpecifier.text; } else if (typescript_1.default.isImportClause(declaration)) { name = declaration.name.text; module = declaration.parent.moduleSpecifier.text; } else { return null; } return { name, module }; } return null; }