Skip to content

Commit

Permalink
feat(material/schematics): initial setup for template migrations (#24515
Browse files Browse the repository at this point in the history
)

* feat(material/schematics): initial setup for template migrations

* created TemplateMigration for migrating templates
* added it to the migrations for the mdc-migration schematic
  • Loading branch information
wagnermaciel authored and mmalerba committed Jul 15, 2022
1 parent a12f268 commit f24a49f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 1 deletion.
Expand Up @@ -16,6 +16,7 @@ ts_library(
deps = [
"//src/cdk/schematics",
"@npm//@angular-devkit/schematics",
"@npm//@angular/compiler",
"@npm//@types/node",
"@npm//postcss",
"@npm//postcss-scss",
Expand Down
3 changes: 2 additions & 1 deletion src/material/schematics/ng-generate/mdc-migration/index.ts
Expand Up @@ -10,6 +10,7 @@ import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics';
import {Schema} from './schema';
import {DevkitFileSystem, UpdateProject, findStylesheetFiles} from '@angular/cdk/schematics';
import {ThemingStylesMigration} from './rules/theming-styles';
import {TemplateMigration} from './rules/template-migration';
import {MIGRATORS} from './rules';
import {dirname} from 'path';
import {StyleMigrator} from './rules/style-migrator';
Expand Down Expand Up @@ -78,7 +79,7 @@ export default function (options: Schema): Rule {
const additionalStylesheetPaths = findStylesheetFiles(tree, migrationDir);
const project = new UpdateProject(context, program, fileSystem, new Set(), context.logger);
const {hasFailures} = project.migrate(
[ThemingStylesMigration],
[ThemingStylesMigration, TemplateMigration],
null,
migrators,
additionalStylesheetPaths,
Expand Down
Expand Up @@ -12,6 +12,7 @@ import {runfiles} from '@bazel/runfiles';
const TS_CONFIG = '/projects/material/tsconfig.app.json';

export const THEME_FILE = '/projects/material/src/theme.scss';
export const TEMPLATE_FILE = '/projects/material/src/app/app.component.html';

export function createNewTestRunner(): SchematicTestRunner {
return new SchematicTestRunner(
Expand Down
@@ -0,0 +1,23 @@
import {createTestApp, patchDevkitTreeToExposeTypeScript} from '@angular/cdk/schematics/testing';
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
import {createNewTestRunner, migrateComponent, TEMPLATE_FILE} from './components/test-setup-helper';

describe('template migrations', () => {
let runner: SchematicTestRunner;
let cliAppTree: UnitTestTree;

async function runMigrationTest(oldFileContent: string, newFileContent: string) {
cliAppTree.overwrite(TEMPLATE_FILE, oldFileContent);
const tree = await migrateComponent('card', runner, cliAppTree);
expect(tree.readContent(TEMPLATE_FILE)).toBe(newFileContent);
}

beforeEach(async () => {
runner = createNewTestRunner();
cliAppTree = patchDevkitTreeToExposeTypeScript(await createTestApp(runner));
});

it('should do nothing yet', async () => {
await runMigrationTest('<h1>Hello</h1>', '<h1>Hello</h1>');
});
});
@@ -0,0 +1,56 @@
/**
* @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
*/

import {Migration, ResolvedResource} from '@angular/cdk/schematics';
import {SchematicContext} from '@angular-devkit/schematics';
import {StyleMigrator} from './style-migrator';
import * as compiler from '@angular/compiler';

/**
* Traverses the given tree of nodes and runs the given callbacks for each Element node encountered.
*
* Note that updates to the start tags of html element should be done in the postorder callback,
* and updates to the end tags of html elements should be done in the preorder callback to avoid
* issues with line collisions.
*
* @param nodes The nodes of the ast from a parsed template.
* @param preorderCallback A function that gets run for each Element node in a preorder traversal.
* @param postorderCallback A function that gets run for each Element node in a postorder traversal.
*/
function visitElements(
nodes: compiler.TmplAstNode[],
preorderCallback: (node: compiler.TmplAstElement) => void = () => {},
postorderCallback: (node: compiler.TmplAstElement) => void = () => {},
): void {
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node instanceof compiler.TmplAstElement) {
preorderCallback(node);
visitElements(node.children, preorderCallback, postorderCallback);
postorderCallback(node);
}
}
}

export class TemplateMigration extends Migration<StyleMigrator[], SchematicContext> {
enabled = true;

override visitTemplate(template: ResolvedResource) {
const ast = compiler.parseTemplate(template.content, template.filePath, {
preserveWhitespaces: true,
preserveLineEndings: true,
leadingTriviaChars: [],
});

visitElements(ast.nodes, node => {
// TODO(wagnermaciel): implement the migration updates.
});

this.fileSystem.overwrite(template.filePath, template.content);
}
}

0 comments on commit f24a49f

Please sign in to comment.