Grunt: Copy directory where dir name is dynamic?

225 Views Asked by At

I am decking out my own version of Yii2 advanced with Grunt to handle everything. From resetting Yii2 back to factory (removing -local.php, cleaning logs, assets, etc), using Gulp for asset handling, combining and minifying CSS and JS, with LESS, SCSS, TS support. I am trying to make everything easier and better with Grunt, for all the things I need.

I have templates that I work from (extended controller, models, config, theme, layouts, views) all custom. I also am wanting to include the default (untouched) yii2 templates for basic, frontend, common, etc. Just so if needed, they are there and I don't have to copy-n-paste from a clean yii2 repo.

I built a _templates directory in the root of my yii2 advanced app. Inside it I have a yii2 directory. Inside that default directory for the default templates, which has backend, frontend, etc. which are the untouched templates. Then I have under the yii2 dir, custom where my custom templates will be. So here is a general structure:

├── _templates
│   └── yii2
│       └── default
│           └── backend
│           └── frontend
│       └── custom
│           └── backend
│           └── frontend

Now, if I want to make another section (app), I want to just run:

gulp new-app --template=yii2/custom/frontend --name=mobile and have it copy that directory to the root of my app.

It also has a placeholder in the files for the namespace. So if I name it "mobile", the files inside the template need to have "mobile" for the namespace. So I have added {{%REPLACE-APP-NAME%}} to the files. That is a separate question, but next on my list to handle in case someone answering can help with that too, it would be appreciated.


Where I am at now: My Gruntfile has a list of copy actions, for backend, frontend, and mainsite. These are necessary and used during my build command, to copy over needed files from vendors. I don't want to break this.

I assume I need to add another section to my copy command to handle copying the templates? However, the directory name is not known? How can I pass the directory name to this task?

Gruntfile:

module.exports = function (grunt) {
grunt.initConfig({
    copy: {
        backend: {
            files: [
                {expand: true, flatten: true, src: ['vendor/bower/bootstrap/fonts/*'], dest: 'backend/web/assets/fonts/', filter: 'isFile'},
                {cwd: 'vendor/almasaeed2010/adminlte/dist', src: '**/*', dest: 'backend/web/assets/themes/adminlte', expand: true}
            ]
        },

        frontend: {
            files: [
                {expand: true, flatten: true, src: ['vendor/bower/bootstrap/fonts/*'], dest: 'frontend/web/assets/fonts/', filter: 'isFile'},
                {cwd: 'vendor/almasaeed2010/adminlte/dist', src: '**/*', dest: 'frontend/web/assets/themes/adminlte', expand: true}
            ]
        },

        template: {  // <-- DOES NOT WORK, JUST EXAMPLE
            files: [{
                src: '_templates/' + templatePath + '/**/*', // <-- NOTICE templatePath variable!
                dest: saveName, <-- NOTICE saveName variable
                expand: true
            }]
        },
    },
});

grunt.loadNpmTasks('grunt-contrib-copy');

grunt.registerTask('build', ['less', 'sass_import', 'sass', 'typescript', 'concat', 'cssmin', 'uglify', 'copy']);
grunt.registerTask('build-backend', ['less:backend', 'sass_import:backend', 'sass:backend', 'typescript:backend', 'concat:backend', 'cssmin:backend', 'uglify:backend', 'copy:backend']);
grunt.registerTask('build-frontend', ['less:frontend', 'sass_import:frontend', 'sass:frontend', 'typescript:frontend', 'concat:frontend', 'cssmin:frontend', 'uglify:frontend', 'copy:frontend']);

grunt.registerTask('new-app', function() {
    var templateName = grunt.option('template');
    var saveName = grunt.option('name');

    if ( ! grunt.file.isDir('_templates/' + templateName) ) {
        grunt.warn('Template Not Found!\n' );
    }
    grunt.log.writeln('Chosen Template: ' + templateName);
    // do work here :)
    grunt.log.writeln('Done!');
});

Then the command: grunt new-app --template=yii2/default/frontend --name=mobile

The template option simply is the path to the template for copying from. The name option, will be the name to copy the directory as. ie: final name it will be called in the app root once copied over.

How can I call the copy command from within my new-app task? I added a template action to the copy task (as shown above in example). How can I get the variables to work, or what is the best way to handle this?

1

There are 1 best solutions below

0
user2926055 On

You can run a grunt task inside a registered task with grunt.task.run:

grunt.log.writeln('Chosen Template: ' + templateName);
grunt.task.run(['copy:' + templateName]);