13

To concatenate two files, it looks something like this:

  concat: {
    src: ['common.js','js/app.js'],
    dest: 'assets/js/app.js'
  }

And if I want to concat an entire folder of files into one, it looks something like this:

  concat: {
    src: ['dev/*.js','],
    dest: 'prod/js/app.js'
  }

But let's say I have a file that I want to concat onto 10 or 20 other files, and I want them to concat separately? In other words, here is what I'm looking for:

A.js + B.js = AB.js
A.js + C.js = AC.js
A.js + D.js = AD.js
A.js + E.js = AE.js

And so on... To be more specific though, I can figure out how to concat files one by one as described, but I want to figure out how to specify A.js from the example, and have it concat onto any file in a specified path. So what I want is:

A.js + dev/*.js = AB.js, AC.js, AD.js, AE.js ...

In pseudo-code, here is what I want:

  concat: {
    src: ['common.js', 'dev/*.js','], // common.js gets concatenated to each file in this directory
    dest: 'prod/js/*.js' // each file in src gets saved separately in dest 
  }

I'd appreciate any help, I've have a hard time finding info on how to do this

jonschlinkert
  • 10,872
  • 4
  • 43
  • 50
  • If anyone needs a similar thing, this plugin does just that https://www.npmjs.org/package/grunt-wrap2000 – Tetaxa Apr 25 '14 at 08:06
  • all you need to do is use the banner and footer options in grunt-contrib-concat. If you want to prepend an entire file, just do `banner: require('./foo.js')`. same with footer. – jonschlinkert Apr 28 '14 at 00:14

1 Answers1

19

Grunt's built-in concat task (I recommend looking at the source btw) does not support anything like dest: 'prod/js/*.js', you would have to specify each output target separately which is an overkill in your case.

Your best bet is to just write your own code (perhaps wrap it in your custom task), it's quite simple. Here's a simple wrap multitask. Don't promise it's robust and safe to use :)

  grunt.registerMultiTask('wrap', 'Wraps source files with specified header and footer', function() {
        var data = this.data,
            path = require('path'),
            dest = grunt.template.process(data.dest),
            files = grunt.file.expandFiles(this.file.src),
            header = grunt.file.read(grunt.template.process(data.header)),
            footer = grunt.file.read(grunt.template.process(data.footer)),
            sep = grunt.utils.linefeed; 

        files.forEach(function(f) {
            var p = dest + '/' + path.basename(f),
                contents = grunt.file.read(f);

            grunt.file.write(p, header + sep + contents + sep + footer);
            grunt.log.writeln('File "' + p + '" created.');
        });
  });

Feed it with a config like this:

wrap: {
    html: {
        header: '<%= project.partials %>/head.html',
        footer: '<%= project.partials %>/footer.html',
        src: [
            '<%= project.pages %>/index.html',
            '<%= project.pages %>/about.html',
            '<%= project.pages %>/blog.html'
        ],
        dest: '.'   // destination *directory*, probably better than specifying same file names twice
    }
}

Just in case I also updated your fiddle: http://jsfiddle.net/dipish/hKkGX/

Dmitry Pashkevich
  • 13,431
  • 9
  • 55
  • 73
  • To clarify, I would like for each file to concat separately, so can you also do dest: 'prod/js/*.js' ? And thanks for your answer! – jonschlinkert Oct 05 '12 at 16:38
  • it looks like it should, but I can't get it to work. I know this is a lot to ask, any chance you could put this inside an example grunt file? here is a jsfiddle with my grunt file - just for easier reading http://jsfiddle.net/rRpeg/ – jonschlinkert Oct 08 '12 at 15:45
  • Ok looks like the problem is that the `concat` helper can only accept file paths as parameters, not strings already read from files. I guess I shouldn't rely on it – Dmitry Pashkevich Oct 08 '12 at 16:36
  • thanks for the work you're doing on this, however just to clarify, the grunt file I put on jsfiddle was an example for what I'm doing now, but the reason for this question is that the actual project will have hundreds of files, so specifying output targets won't be practical. Thanks again for giving this so much attention! I really appreciate it – jonschlinkert Oct 08 '12 at 17:23
  • You're weIlcome. I recently started playing around with grunt so I'm curious about what other people are trying to do with it :) But my suggested solution doesn't require you to specify output targets, just the directory where they will all go. And you can specify source paths with wildcads e.g. `articles/*.html` will work. – Dmitry Pashkevich Oct 08 '12 at 21:15
  • Also, I think you should edit your question to better reflect what you're actually trying to do (wrap html articles in header and footer), because the example with js files looks too synthetic in this case... – Dmitry Pashkevich Oct 08 '12 at 21:18
  • Dmitry, thanks again. And to clarify, my question asks exactly what I'm trying to do, please don't get hung up on the html example I used. That was just an example that was easy to use out of context, the question states what I want. One implementation of concatenating files using wildcards is the example I gave, but the project is so much more complicated and varied than that. and in reality will apply to js, css, html less and so on, and with thousands of files. So whether or not those files are HTML is arbitrary to the question. If I can get this to work as asked, I'll be in good shape. – jonschlinkert Oct 09 '12 at 19:11
  • just to add to my last point, after I made the earlier comment about having "hundreds of files" I actually check how many were in the project, and it's in the thousands. So it's just not feasible to specify file names for some of the tasks that require what I'm asking about. – jonschlinkert Oct 09 '12 at 19:14
  • yes! in fact it does, sorry for the late reply. Your code definitely makes the process easier for me, and as it stands I think it's my best bet. Thanks! – jonschlinkert Oct 10 '12 at 23:47
  • Dmitry, did you know that, with the code you provided, using a wildcard for src does actually work? I just tried it to see if would work so I wouldn't have to explicitly specify each "page". Thanks again! – jonschlinkert Oct 23 '12 at 20:48
  • Yes, and I mentioned that in an earlier comment :) http://stackoverflow.com/questions/12722855/using-grunt-concat-how-would-i-automate-the-concatenation-of-the-same-file-to-m/12749861#comment17291008_12749861 – Dmitry Pashkevich Oct 24 '12 at 06:12
  • This works thanks to [`grunt.file.expandFiles`](https://github.com/gruntjs/grunt/blob/master/docs/api_file.md#gruntfileexpandfiles), the routine takes care of the wildcards. – Dmitry Pashkevich Oct 24 '12 at 08:56
  • You did mention that! I see it now, for some reason when I read it the first time I thought you said I "cannot" specify source paths with a wildcard... very cool :) – jonschlinkert Oct 25 '12 at 01:41