Skip to content

Instantly share code, notes, and snippets.

@eschwartz
Created February 5, 2015 14:44
Show Gist options
  • Save eschwartz/9876bb8166d1a98d483b to your computer and use it in GitHub Desktop.
Save eschwartz/9876bb8166d1a98d483b to your computer and use it in GitHub Desktop.
A grunt task for when you need to use RequireJS `paths` config in a TypeScript project.
module.exports = function(grunt) {
var path = require('path');
grunt.registerMultiTask(
'tsd-amd',
'Generates a TypeScript definition file for a set of *.ts files. ' +
'The output will contain declared modules for every *.ts file, ' +
'which are named according to their AMD ids.',
function() {
var options = this.options({
// path aliases
paths: {},
template: 'declare module "{amdId}" {\n' +
'\timport X = require("{requirePath}");\n' +
'\texport = X;\n' +
'}\n\n'
});
this.files.forEach(function(fileObj) {
var amdModuleDeclarations = fileObj.src.
reduce(function(str, srcPath) {
var amdId = filePathToAmd(srcPath, options.paths, '.ts');
var requirePath = withoutExt(
relativePath(fileObj.dest, srcPath),
'.ts'
);
return str + options.template.
replace('{amdId}', amdId).
replace('{requirePath}', requirePath);
}, '');
grunt.file.write(fileObj.dest, amdModuleDeclarations);
});
/**
* Convert a file path to an AMD module id.
*
* @param {string} filePath
* @param {Object} pathAliases as { 'alias-name': 'some/file/path' }
* @param {string} ext file extension
* @return {string}
*/
function filePathToAmd(filePath, pathAliases, ext) {
return Object.keys(pathAliases).
reduce(function(amdId, alias) {
var path = options.paths[alias];
var isMatchingAlias = amdId.indexOf(path) === 0;
if (isMatchingAlias) {
return amdId.replace(path, alias);
}
}, withoutExt(filePath, ext));
}
function withoutExt(path, ext) {
return path.split(ext)[0];
}
function relativePath(from, to) {
var relDir = path.relative(
path.dirname(from),
path.dirname(to)
);
return relDir ?
[relDir, path.basename(to)].join('/') :
path.basename(to);
}
}
)
;
};
@eschwartz
Copy link
Author

Important note:
The reason I have not published a repo for this grunt task is that it is not really in "finished" form. That is to say, there are no tests and I have only used it under very specific conditions.

So use at your own risk, and consider this more of a jumping-off point than a completed library. As soon as I need to use it on another project, or I run into a use case I didn't account for, I'll probably break it off into its own project. If anyone wants to take a shot at adapting this into their own thing, I hereby grant you permission to do so.

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