Utilities for handling *.hbs files as abstract syntax tree
npm install @codemod-utils/ast-template
_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.
``ts
import { AST } from '@codemod-utils/ast-template';
function transform(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: Handlebarsember-template-recast
- Parser: ember-template-recast
- Transform:
Copy-paste the visit methods from your file to AST explorer, then rename AST.builders to b.
`ts
/ Your file /
import { AST } from '@codemod-utils/ast-template';
function transform(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);
}
`
`ts
/ 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 v20 or above
See the Contributing guide for details.
This project is licensed under the MIT License.