How to make grunt-contrib-copy not copy LESS files? - gruntjs

I have the following Gruntfile:
module.exports = function(grunt) {
//Project configuration.
grunt.initConfig({
copy: {
main: {
files: [
{
expand: true,
cwd: "source/",
src: ["!**/*.less", "**"],
dest: "compiled/"
},
],
},
},
});
grunt.loadNpmTasks("grunt-contrib-copy");
grunt.registerTask("default", ["copy"]);
};
My goal is to have it copy everything from the source folder to the compiled folder. For example, if this was my file structure before running Grunt...
[root]
- Gruntfile.js
- source
\- test.txt
\- sample.html
\- file.less
- compiled
...I am expecting to get...
[root]
- Gruntfile.js
- source
\- test.txt
\- sample.html
\- file.less
- compiled
\- test.txt
\- sample.html
...but instead I get:
[root]
- Gruntfile.js
- source
\- test.txt
\- sample.html
\- file.less
- compiled
\- test.txt
\- sample.html
\- file.less
I thought that setting the source to ["!**/*.less", "**"] would fix this, but that isn't the case. Why doesn't this work (what is it actually targeting) and how can I fix this?

Negating patterns should be placed after matching patterns since they negate the previous match:
copy: {
main: {
files: [
{
expand: true,
cwd: "source/",
src: ["**", "!**/*.less"],
dest: "compiled/"
},
],
},
}
See the globbing patterns docs for examples, like:
// All files in alpha order, but with bar.js at the end.
{src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...}
By placing "**" after your negating pattern, you're overriding it.

Related

How to skip source parent directory using grunt uglify

src directory:
dir1
|-- 1.js
|-- 2.js
`-- sub-dir1
`-- 1.js
dest directory:
min
`-- dir1
|-- 1.min.js
|-- 2.min.js
`-- sub-dir1
`-- 1.min.js
My code snippet:
uglify: {
t2: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */'
},
files: [{
expand: true,
src: ['dir1/**/*.js'],
dest: 'min',
rename: function (dst, src) {
return dst + '/' + src.replace('.js', '.min.js');
}
}]
}
}
But I want to skip source directory under destination directory, desired structure is:
min
|-- 1.min.js
|-- 2.min.js
`-- sub-dir1
`-- 1.min.js
There's a couple of ways to achieve this. Solution A (below) is the simplest and most commonly used.
Solution A
When building the files object dynamically you can utilize the cwd property. The description of the cwd property in the docs reads:
cwd All src matches are relative to (but don't include) this path.
Change your files property to the following:
// ...
files: [{
expand: true,
cwd: 'dir1/', // <-- Add this.
src: '**/*.js', // <-- Change your src glob to this.
dest: 'min',
rename: function (dst, src) {
return dst + '/' + src.replace('.js', '.min.js');
}
}]
// ...
Solution B
Another way, (without utilizing the cwd property), is to change your rename method to the following instead:
// ...
rename: function (dst, src) {
src = src.split('/');
src.shift();
src = src.join('/');
return dst + '/' + src.replace('.js', '.min.js');
}
// ...
The src = src.split('/'); part utilizes the String split() method with the / separator to split the src path into an array of individual path items.
The src.shift(); part utilizes the Array shift() method to remove the first element from the array (e.g. dir1).
The src = src.join('/') part utilizes the Array join() method with the / separator to form the new path as a String.

grunt-rebase – copy to multiple folders along with flattening the structure

I was wondering if anyone could help me with this.
I have a project where I am creating multiple html pages for different sites. Each of these sites shares a common assets folder (fonts, css, js etc) my directory layout is as follows:
|-- project
| |--assets
| | |—-css
| | |—-images
| | |—-fonts
| | |—-js
| |--site-1
| | |—-index.html
| |--site-2
| | |—-index.html
| |--site-3
| | |—-index.html
What I would like to achieve is the following:
• A 'dist' folder that contains:
|-- dist
| |--site-1
| | |—-index.html
| | |—-style.min.css
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg etc...
| | |—-scripts.min.js
| | |—-font1.otf
| | |—-font2.otf etc...
| |--site-2
| | |—-index.html
| | |—-style.min.css
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg etc...
| | |—-scripts.min.js
| | |—-font1.otf
| | |—-font2.otf etc...
| |--site-3
| | |—-index.html
| | |—-style.min.css
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg etc...
| | |—-scripts.min.js
| | |—-font1.otf
| | |—-font2.otf etc...
Just to explain the desired result:
• each site is 'flattened' within a directory, so that all of the assets, images, js, css, fonts are on the same level as the index.html file. (a requirement of the 3rd party that needs these)
• The corresponding links in each of the .html, .css & .js are updated the reflect the above.
• At times there might be more or less than just 3 'site' folders - so it would be great if I could 'loop' through and detect a folder name convention (??) - just a nice have if anyone smarter than me knows how to do this with a grunt task.
I have been trying the grunt-rebase task to make this work. It sounds like it is what I need, however I am really struggling with the documentation to make it work, along with a lack of experience with grunt tasks.
Any help would be great. If you need any more info please let me know.
EDIT - here is my grunt.js file - I have removed unneeded tasks and other bumpf for clarity.
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: {
main: {
files: [
{expand: true, cwd: 'project/', src: ['**/*'], dest: 'dist/', filter: 'isFile'}
]
}
},
rebase: {
scoped: {
files: [{
//css ref's
expand: true,
cwd: 'dist/assets/css/',
src: '*.css',
dest: 'dist/site-1/',
reference: '../assets/images/',
scopes: {
url: {
'../images/': '',
'../fonts/': ''
}
}
}, {
//html ref's
expand: true,
cwd: 'dist/site-1/',
src: '**/*.html',
dest: 'dist/site-1/',
reference: true,
scopes: {
url: {
'../assets/images/': ''
},
img: {
'../assets/images/': ''
},
link: {
'../assets/css/': ''
},
script: {
'../assets/js/': ''
}
}
}, {
//images
expand: true,
cwd: 'dist/assets/images/',
src: '**/*',
dest: 'dist/site-1/'
}, {
//fonts
expand: true,
cwd: 'dist/assets/fonts/',
src: '**/*',
dest: 'dist/site-1/'
},
{
//js
expand: true,
cwd: 'dist/assets/js/',
src: '*.js',
dest: 'dist/site-1/'
}]
}
}
});
//1 - make copy of entire prod directory to 'dist folder'
//2 - rebase task
//3 - TODO - delete dist/assets folder (not needed after rebase)
grunt.registerTask('Create Exported Project', [
'copy',
'rebase'
]);
};
The above rebase task works....but only for one folder that i hard code into the 'dest' field for each scope (the 'site-1' folder).
I was hoping for some flexibility to be able to loop through all folders that match a condition (maybe the string - 'site-').

Adapt dest folder to ** globbing pattern

I'm working with grunt-contrib-copy. I have this file tree:
`-- src
`-- model
|-- a4
| `-- public
| |-- css
| |-- img
| `-- js
|-- posters
| `-- public
| |-- css
| |-- img
| `-- js
`-- prints
`-- public
|-- css
|-- img
`-- js
I would like to copy the files in
src/model/**/public/img to dist/images/{1}/ where {1} is the folder name (a4, posters, prints... dynamic folders that are bound to change too), so:
src/model/a4/public/img/file.png -> dist/images/a4/file.png
Is there a way to specify that with grunt-contrib-copy (maybe the rename function?) or do I have to iterate manually over the files?
Right now this is what I have:
grunt.registerTask 'images-generate', ->
gruntCopyFiles.images = {
expand: true,
cwd: './src/model/',
src: ["**/public/img/*.png", "**/public/img/*.jpg"],
dest: "./dist/images/"
}
But this copies src/model/a4/public/img/file.png to dist/images/a4/public/img/file.png which is not what I want.
Any suggestion? Thanks!
Is there a way to specify that with grunt-contrib-copy (maybe the rename function?) or do I have to iterate manually over the files?
Utilizing the rename function is the way to achieve this. Glob patterns alone cannot meet your requirement, nor can the flatten option.
Something like the following also copies any subfolders which may potentially reside inside the source img folders:
gruntCopyFiles.images = {
expand: true,
cwd: 'src/model',
dest: 'dist/images',
src: '**/public/img/**/*.{png,jpg,gif}',
rename: function(dest, src) {
var items = src.split('/'),
baseIndex = items.indexOf('img') + 1,
subPath = items.slice(baseIndex, items.length).join('/');
return [dest, items[0], subPath].join('/');
}
}
Example:
src/model/a4/public/img/file.png --> dist/images/a4/file.png
src/model/a4/public/img/quux/file.jpg --> dist/images/a4/quux/file.jpg
Looks like you can use flatten to get stripped-down destination paths:
gruntCopyFiles.images = {
flatten: true,
expand: true,
cwd: './src/model/',
src: ["**/public/img/*.png", "**/public/img/*.jpg"],
dest: "./dist/images/"
}
From the docs:
flatten Remove all path parts from generated dest paths.

Unable to process a file using grunt copy-task

I'm trying to use grunt-contrib-copy (version 0.4.1) to rewrite some strings inside a file during the build process. As a test I can copy the file, so it's not a permissions or location problem.
These are the options for the fileProcessor task (in Coffeescript syntax) to copy the file:
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
rename: (dest, src) ->
grunt.verbose.writeln src, " => ", dest + src.substring(0, src.lastIndexOf("/") + 1) + "foo.js"
dest + src.substring(0, src.lastIndexOf("/") + 1) + "foo.js"
]
I get the following output, everything worked as expected:
Running "copy:fileProcessor" (copy) task
Verifying property copy.fileProcessor exists in config...OK
test-25fd6a1c3a890933.js => target/js/foo.js
Files: target/js/test-25fd6a1c3a890933.js -> target/js/foo.js
Options: processContent=false, processContentExclude=[]
Options: processContent=false, processContentExclude=[]
Copying target/js/test-25fd6a1c3a890933.js -> target/js/foo.js
Reading target/js/test-25fd6a1c3a890933.js...OK
Writing target/js/foo.js...OK
Copied 1 files
So far so good. Clearly grunt-contrib-copy has no problem with the file itself. So I replace the the rename task with a process task, and use a simple regex to see if it works:
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
processContent: (content, src) ->
re = new RegExp("(angular)+")
content.replace(re, "foo")
]
Which produces the following output:
Running "copy:fileProcessor" (copy) task
Verifying property copy.fileProcessor exists in config...OK
Files: target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js -> target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js
Options: processContent=false, processContentExclude=[]
Options: processContent=false, processContentExclude=[]
Copying target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js -> target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js
Reading target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js...OK
Writing target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js...OK
Copied 1 files
So grunt-contrib-copy finds the file I need to process, but the processing never happens. processContent remains set to the default false.
Looking in copy.js, when grunt.file.copy(src, dest, copyOptions) is called, copyOptions is an object with only two properties:
process, which is false, and
noProcess, which is an empty array.
So my process options are never passed along. Any ideas on why this could be?
your processContent is in the wrong place, it needs to be wrapped into options and moved one level higher. Also note that processContent is depreciated and replaced by process
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
]
options:
process: (content, src) ->
re = new RegExp("(angular)+")
content.replace(re, "foo")

Trying to get grunt to copy directory to destination directory

I've been working a lot with grunt lately and trying to get up to speed on all the awesome things I can do with it. What I am attempting to do is set a variable for a src, and one for a destination directory and run a copy task to move my initial build files (updated from another source) to production destination directory. I can get the copy to work with this simple example but it brings over the src directory /build/ to assets
assets/js/build/vendor-library
I'm trying to not copy over the directory name build. so the copy just has the following /assets/js/vendor-library/*
module.exports = (grunt) ->
grunt.initConfig
copy:
main:
expand: "true"
src: "build/vendor-library/*"
dest: "assets/js/"
grunt.loadNpmTasks "grunt-contrib-copy"
grunt.registerTask "default", "copy"
Add the flatten option.
module.exports = (grunt) ->
grunt.initConfig
copy:
main:
expand: "true"
flatten: "true"
src: "build/vendor-library/*"
dest: "assets/js/"
grunt.loadNpmTasks "grunt-contrib-copy"
grunt.registerTask "default", "copy"

Resources