Skip to content

Instantly share code, notes, and snippets.

@nebirhos
Last active May 26, 2019 23:55
Show Gist options
  • Save nebirhos/6a3838b0a61f44f1d6945b8e652479fa to your computer and use it in GitHub Desktop.
Save nebirhos/6a3838b0a61f44f1d6945b8e652479fa to your computer and use it in GitHub Desktop.
Convert AngularJS templateUrl to template with jscodeshift

Convert AngularJS templateUrl to template with jscodeshift

npm install -g [email protected]

jscodeshift -t codemods/templateCacheToWebpackImport.js src/

See https://github.com/cpojer/js-codemod

normal mode

jscodeshift -d -t codemods/templateCacheToWebpackImport.js path/to/js

debug mode

node --debug-brk --inspect `which jscodeshift` --run-in-band -p -d -t codemods/templateCacheToWebpackImport.js codemods/test.js
/**
* Codemod to replace templateUrl with imported templates.
*
* Example:
*
* ```
* angular.module('myapp').component('myappDialog', { templateUrl: '/partials/dialog.html' });
*
* =>
*
* import template from '/partials/dialog.html';
* angular.module('myapp').component('myappDialog', { template });
* ```
*
* References
* * https://github.com/cpojer/js-codemod/blob/master/transforms/object-shorthand.js
*
* @author Francesco Disperati
* @since 2018-01-03
*/
function transformer (file, api) {
const j = api.jscodeshift;
let root = j(file.source);
let stats = { count: 0 };
return root
.find(j.ObjectExpression)
.find(j.Property)
.filter(p => filterTemplateUrl(p, stats))
.forEach(p => {
let templateName = getTemplateName(j, p.node);
let templatePath = `../../partials/${templateName}`;
addImportTemplateAtFileTop(j, root, templatePath);
// Replace property with key shorthand
p.value.key = 'template';
p.value.shorthand = true;
})
.toSource({
quote: 'single',
reuseWhitespace: false
});
}
function filterTemplateUrl(path, stats) {
if (path.node.key.name == 'templateUrl') {
stats.count += 1;
// We assume there is no more than 1 template per file
if (stats.count > 1) {
throw new Error('too many templatUrls!');
}
return true;
}
}
/*
* Extract the name of the HTML template from the passed property.
* templateUrl can be a concatenation of strings literal,
* so we concatenate all the literals and extract the last part.
*/
function getTemplateName(j, property) {
return j(property)
.find(j.Literal)
.nodes()
.map(n => n.value)
.join('')
.split('/')
.pop();
}
function addImportTemplateAtFileTop(j, root, templatePath) {
let importStatement = j.importDeclaration(
[j.importDefaultSpecifier(j.identifier('template'))],
j.literal(templatePath)
);
root.get().node.program.body.unshift(importStatement);
}
module.exports = transformer;
@BBlackwo
Copy link

BBlackwo commented Sep 4, 2018

Thanks for this! Works great! Only catch is it doesn't work with template literals.

Line 65 fails .find(j.Literal).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment