23

I just started using grunt, and love it. I keep running into an issue that seems like it might be pretty common. Here it is. I have files named so that words after a dot are something like classes. eg:

layout.coffee
layout.blog.coffee
layout.site.coffee

My grunt task is configured to watch these files and translate them to js like this:

coffee:
  dev:
    files: [
      expand: true
      cwd: "<%= yeoman.app %>"
      src: ["**/*.coffee"]
      dest: "<%= yeoman.dev %>"
      ext: ".js"
    ]

The problem, I think, is that using ext makes the target for all three .coffee files the destination file layout.js, which isn't the intention.

Is there a nice way to configure grunt file mapping for filenames with multiple dots?

Right now I have to change my naming convention to use - instead of ., which is a drag :(

SimplGy
  • 20,079
  • 15
  • 107
  • 144

3 Answers3

31

Note that there is another option "extDot" that you can use to specify after which dot the ext should apply (first or last):

E.g.

files: [{
  expand: true,
  src: ['*.js','!*min.js'],
  dest: 'js',
  cwd: 'js',
  ext: '.min.js',
  extDot: 'last'
}]
ViniH
  • 756
  • 1
  • 7
  • 12
  • 3
    That is perfectly valid, `extDot` was added in Grunt version 0.4.3. Just a note: unfortunately you may have a file named `filename.min.eco.js` (an Eco template precompiled to JST and then minified) in which case the extension is neither after the first dot, nor after the last (but still technically it is `js`). Another example would be `underscore.string.min.js.gz`. It's debatable and it's good to have options suiting everybody's needs to achieve what they want to. – Radko Dinev Aug 21 '14 at 09:43
  • To solve that they could change extDot to specify the nth dot - but I am guessing the use case is so small as to not have been required in the interim half a decade. – ViniH Dec 18 '20 at 21:31
12

Take a look at the "Building the files object dynamically" section of Configuring Tasks.

Instead of specifying ext, you can specify rename which is a function that lets you create your own mapping for the file names.

The problem you are running into was brought up as an issue on github and the answer from the grunt folks was that the "extension" of a file should be everything after the first "." instead of the last.

Hope that helps you!

Radko Dinev
  • 865
  • 7
  • 15
go-oleg
  • 19,272
  • 3
  • 43
  • 44
  • 3
    Sure does. Looks like the Grunt team has taken a firm position on this one already. – SimplGy May 22 '13 at 19:40
  • FYI the **Configuring Tasks** documentation has moved [here](https://gruntjs.com/configuring-tasks) now. – mminc Aug 02 '19 at 18:13
11

That's the workaround I'm using in my projects:

uglify  : {
  build : {
    src     : ['**/*.js', '!*.min.js'],
    cwd     : 'js/',
    dest    : 'js/',
    expand  : true,
    rename  : function (dest, src) {
      var folder    = src.substring(0, src.lastIndexOf('/'));
      var filename  = src.substring(src.lastIndexOf('/'), src.length);

      filename  = filename.substring(0, filename.lastIndexOf('.'));

      return dest + folder + filename + '.min.js';
    }
  }
}

When the filename is like jquery.2.0.3.js then after minifying that it will be jquery.2.0.3.min.js.

sunpietro
  • 2,059
  • 4
  • 24
  • 42