How do I process multiple files as templates with yeoman generator?

5.5k Views Asked by At

I'm working on a custom generator that I originally wrote with grunt-init. One difference I'm noticing is grunt-init automatically processes all the files in root as templates but with yeoman generator you have to do this using .template(). I'm familiar with how to process any individual file with .template() but is it possible to process an entire directory?

3

There are 3 best solutions below

0
Ryan Lynch On

Looking at the Yeoman generator code, there doesn't seem to be a built in way to do this. The way I solved this was to copy some of the code from the built in generator code and modify it for my needs. I determine if a file is a template based on the _ prefix convention since I want to rename the files to exclude that prefix, but you could just treat every file as a template and it would work fine. This will copy all of the files in the directory, so what I also did is to exclude the .DS_STORE files that you find by default on OSX, but since that is a specific case I didn't include that here.

require('path');

MyGenerator.prototype._processDirectory = function(source, destination) {
    var root = this.isPathAbsolute(source) ? source : path.join(this.sourceRoot(), source);
    var files = this.expandFiles('**', { dot: true, cwd: root });

    for (var i = 0; i < files.length; i++) {
        var f = files[i];
        var src = path.join(root, f);
        if(path.basename(f).indexOf('_') == 0){
            var dest = path.join(destination, path.dirname(f), path.basename(f).replace(/^_/, ''));
            this.template(src, dest);
        }
        else{
            var dest = path.join(destination, f);
            this.copy(src, dest);
        }
    }
};
4
dabeng On

This issue is an annoying one. I came across this when I used yeoman for the first time. I think the below code snippet can help you.

this.directory('scripts', 'scripts');// script is folder name
2
Danielo515 On

Yeoman uses mem-fs-editor, which has support for glob patterns. However the documentation is not very clear, and you may miss that point. Here is the documentation of copyTpl, that says it accepts the same options as copy. So since copy has suppport for glob patterns, copyTpl too.

At any point on your yeoman generator you can do:

    const from = 'myFolder/**.js'
    const to = 'project/'
    this
        .fs
        .copyTpl(
             this.templatePath(from), 
             this.destinationPath(to), 
             this.props, {interpolate: /<%=([\s\S]+?)%>/g}
        );
},

Not that, if you are using a glob pattern the destination path should be a folder.