UNPKG

@angular/material

Version:
137 lines 8.07 kB
"use strict"; /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ Object.defineProperty(exports, "__esModule", { value: true }); const schematics_1 = require("@angular/cdk/schematics"); const ts = require("typescript"); const ripple_speed_factor_1 = require("./ripple-speed-factor"); /** Regular expression that matches [matRippleSpeedFactor]="$NUMBER" in templates. */ const speedFactorNumberRegex = /\[matRippleSpeedFactor]="(\d+(?:\.\d+)?)"/g; /** Regular expression that matches [matRippleSpeedFactor]="$NOT_A_NUMBER" in templates. */ const speedFactorNotParseable = /\[matRippleSpeedFactor]="(?!\d+(?:\.\d+)?")(.*)"/g; /** * Note that will be added whenever a speed factor expression has been converted to calculate * the according duration. This note should encourage people to clean up their code by switching * away from the speed factors to explicit durations. */ const removeNote = `TODO: Cleanup duration calculation.`; /** * Rule that walks through every property assignment and switches the global `baseSpeedFactor` * ripple option to the new global animation config. Also updates every class member assignment * that refers to MatRipple#speedFactor. */ class RippleSpeedFactorRule extends schematics_1.MigrationRule { constructor() { super(...arguments); // Only enable this rule if the migration targets version 7 as the ripple // speed factor has been removed in that version. this.ruleEnabled = this.targetVersion === schematics_1.TargetVersion.V7; } visitNode(node) { if (ts.isBinaryExpression(node)) { this._visitBinaryExpression(node); } else if (ts.isPropertyAssignment(node)) { this._visitPropertyAssignment(node); } } visitTemplate(template) { let match; while ((match = speedFactorNumberRegex.exec(template.content)) !== null) { const newEnterDuration = ripple_speed_factor_1.convertSpeedFactorToDuration(parseFloat(match[1])); this._replaceText(template.filePath, template.start + match.index, match[0].length, `[matRippleAnimation]="{enterDuration: ${newEnterDuration}}"`); } while ((match = speedFactorNotParseable.exec(template.content)) !== null) { const newDurationExpression = ripple_speed_factor_1.createSpeedFactorConvertExpression(match[1]); this._replaceText(template.filePath, template.start + match.index, match[0].length, `[matRippleAnimation]="{enterDuration: (${newDurationExpression})}"`); } } /** Switches binary expressions (e.g. myRipple.speedFactor = 0.5) to the new animation config. */ _visitBinaryExpression(expression) { if (!ts.isPropertyAccessExpression(expression.left)) { return; } // Left side expression consists of target object and property name (e.g. myInstance.val) const leftExpression = expression.left; const targetTypeNode = this.typeChecker.getTypeAtLocation(leftExpression.expression); if (!targetTypeNode.symbol) { return; } const targetTypeName = targetTypeNode.symbol.getName(); const propertyName = leftExpression.name.getText(); const filePath = leftExpression.getSourceFile().fileName; if (targetTypeName === 'MatRipple' && propertyName === 'speedFactor') { if (ts.isNumericLiteral(expression.right)) { const numericValue = parseFloat(expression.right.text); const newEnterDurationValue = ripple_speed_factor_1.convertSpeedFactorToDuration(numericValue); // Replace the `speedFactor` property name with `animation`. this._replaceText(filePath, leftExpression.name.getStart(), leftExpression.name.getWidth(), 'animation'); // Replace the value assignment with the new animation config. this._replaceText(filePath, expression.right.getStart(), expression.right.getWidth(), `{enterDuration: ${newEnterDurationValue}}`); } else { // Handle the right expression differently if the previous speed factor value can't // be resolved statically. In that case, we just create a TypeScript expression that // calculates the explicit duration based on the non-static speed factor expression. const newExpression = ripple_speed_factor_1.createSpeedFactorConvertExpression(expression.right.getText()); // Replace the `speedFactor` property name with `animation`. this._replaceText(filePath, leftExpression.name.getStart(), leftExpression.name.getWidth(), 'animation'); // Replace the value assignment with the new animation config and remove TODO. this._replaceText(filePath, expression.right.getStart(), expression.right.getWidth(), `/** ${removeNote} */ {enterDuration: ${newExpression}}`); } } } /** * Switches the global option `baseSpeedFactor` to the new animation config. For this * we assume that the `baseSpeedFactor` is not used in combination with individual * speed factors. */ _visitPropertyAssignment(assignment) { // For switching the `baseSpeedFactor` global option we expect the property assignment // to be inside of a normal object literal. Custom ripple global options cannot be // witched automatically. if (!ts.isObjectLiteralExpression(assignment.parent)) { return; } // The assignment consists of a name (key) and initializer (value). if (assignment.name.getText() !== 'baseSpeedFactor') { return; } // We could technically lazily check for the MAT_RIPPLE_GLOBAL_OPTIONS injection token to // be present, but it's not right to assume that everyone sets the ripple global options // immediately in the provider object (e.g. it can happen that someone just imports the // config from a separate file). const { initializer, name } = assignment; const filePath = assignment.getSourceFile().fileName; if (ts.isNumericLiteral(initializer)) { const numericValue = parseFloat(initializer.text); const newEnterDurationValue = ripple_speed_factor_1.convertSpeedFactorToDuration(numericValue); // Replace the `baseSpeedFactor` property name with `animation`. this._replaceText(filePath, name.getStart(), name.getWidth(), 'animation'); // Replace the value assignment initializer with the new animation config. this._replaceText(filePath, initializer.getStart(), initializer.getWidth(), `{enterDuration: ${newEnterDurationValue}}`); } else { // Handle the right expression differently if the previous speed factor value can't // be resolved statically. In that case, we just create a TypeScript expression that // calculates the explicit duration based on the non-static speed factor expression. const newExpression = ripple_speed_factor_1.createSpeedFactorConvertExpression(initializer.getText()); // Replace the `baseSpeedFactor` property name with `animation`. this._replaceText(filePath, name.getStart(), name.getWidth(), 'animation'); // Replace the value assignment with the new animation config and remove TODO. this._replaceText(filePath, initializer.getStart(), initializer.getWidth(), `/** ${removeNote} */ {enterDuration: ${newExpression}}`); } } _replaceText(filePath, start, width, newText) { const recorder = this.getUpdateRecorder(filePath); recorder.remove(start, width); recorder.insertRight(start, newText); } } exports.RippleSpeedFactorRule = RippleSpeedFactorRule; //# sourceMappingURL=ripple-speed-factor-rule.js.map