Utilities for handling *.hbs
files as abstract syntax tree
@codemod-utils/ast-template
provides methods from ember-template-recast
to help you parse and transform *.hbs
files.
import { AST } from '@codemod-utils/ast-template';
function transformCode(file: string): string {
const traverse = AST.traverse();
const ast = traverse(file, {
/* Use AST.builders to transform the tree */
});
return AST.print(ast);
}
In the traverse
call, you can specify how to visit the nodes of interest ("visit methods") and how to modify them ("builders").
Currently, ember-template-recast
lacks documentation and tutorials. This is unfortunate, given the large amount of builders and visit methods that it provides to help you transform code.
I recommend using AST Explorer to test a small piece of code and familiarize with the API. The error messages from TypeScript, which you can find in your browser's console, can sometimes help. AST Workshop provides a good starting point for Handlebars.
If you intend to publish your codemod, I recommend using @codemod-utils/tests
(create and test file fixtures) to check the output and prevent regressions.
Select the following options to create a 4-tab window:
- Language:
Handlebars
- Parser:
ember-template-recast
- Transform:
ember-template-recast
Copy-paste the visit methods from your file to AST explorer, then rename AST.builders
to b
.
Example
/* Your file */
import { AST } from '@codemod-utils/ast-template';
function transformCode(file) {
const traverse = AST.traverse();
const ast = traverse(file, {
AttrNode(node) {
if (node.name !== 'local-class') {
return;
}
node.name = 'class';
const attributeValue = node.value.chars.trim();
node.value = AST.builders.mustache(
AST.builders.path(`this.styles.${attributeValue}`),
);
},
});
return AST.print(ast);
}
/* AST Explorer */
module.exports = function(env) {
const b = env.syntax.builders;
return {
AttrNode(node) {
if (node.name !== 'local-class') {
return;
}
node.name = 'class';
const attributeValue = node.value.chars.trim();
node.value = b.mustache(
b.path(`this.styles.${attributeValue}`),
);
},
};
};
@codemod-utils/ast-template
avoids re-exporting the types from ember-template-recast
. This is to prevent a change in their API from catastrophically affecting your code.
When you write a function that depends on their implementation, type what you don't own as unknown
, then use @ts-ignore
or @ts-expect-error
as needed.
Most importantly, write tests to document the inputs and outputs of your codemod. When there is an API change, you can refactor code with ease and confidence.
- Node.js v18 or above
See the Contributing guide for details.
This project is licensed under the MIT License.