Transforming multiple JSX files - javascript

Is there a way to specify multiple source -> destination mappings when transforming jsx files to js files using browserify in grunt?
I have the following in Gruntfile.js that supports a single file transformation, but I was hoping to be able to specify a second mapping for another file. I know I can map based on wild card into a single combined destination file. However, that is not what I want since I don't want an "all or nothing" include of the react components on my various pages. Some of the components only apply to a few pages and should not be included everywhere.
browserify: {
options: {
transform: [ require('grunt-react').browserify ]
},
//How do I map a second file here without a wild card?
client: {
src: ['react_components/src/component1.jsx'],
dest: 'react_components/build/component1.js'
}
}
Essentially what I hoped for is a way to provide an array of src-dest mappings in the same task in order to create multiple destination files:
client: [{
src: ['react_components/src/component1.jsx'],
dest: 'react_components/build/component1.js'
}]
Something like the above json

As for me, I do not use browserify, I use grunt-react and react-tools. grunt react allows user to define dynamic_mappings, based on regular expressions, something like this:
//Gruntfile.js
grunt.initConfig({
react: {
dynamic_mappings: {
files: [
/* Controllers compiling. */
{
expand: true,
cwd: './app/scripts/controllers/src',
src: ['**/*.jsx'],
dest: './app/scripts/controllers/dest',
ext: '.js'
},
/* ui-components compiling */
{
expand: true,
cwd: './app/scripts/ui-components/src',
src: ['**/**.jsx'],
dest: './app/scripts/ui-components/dest',
ext: '.js'
},
/* JSX test compiling */
{
expand: true,
cwd: './test/ui-components/src',
src: ['**/**.jsx'],
dest: './test/ui-components/dest',
ext: '.test.js'
}
]
}
}
});

Related

grunt sass and js autoloader

I've tried a few things but can't come to a good solution.
I'm using grunt to compile my sass and minify my javascript.
Is it possible to autoload every .sass file and every .js file in a specific directory?
I've tried stuff like this
sass: {
options: {
sourceMap: false
},
dist: {
src: 'src/sass/**/*.sass',
dest: 'dist/css/style.css'
}
}
but this will only load the very first sass file.
I'm not sure what concat even does but I tried it aswell and didn't find the solution I was looking for.
Basicly all files in the folder sass/ should be compiled to 1 big style.css file the same with javascript.
Sure I could manually import each file in a main.sass file or so, but I would love a autoload function so I don't get lazy and don't create new files because I would have to add them.
edit:
So with this
files: [{
expand: true,
cwd: "src/sass/",
src: ["**/*.sass"],
dest: "dest/css",
ext: ".css"
}]
I can actually do what I want. The problem is my mixins get loaded too late and it's thorwing an error because it doesn't find the mixin I wanted to include.
This is a format to generate a single output file from multiple source files:
concat: {
whatever: {
options: { separator: '\n' },
src: ['src/sass/**/*.sass'],
dest: 'build/tmp.sass' // make sure the temporary build/ dir exists!
}
}
It only works on tasks supporting combining multiple files; in this case the grunt-contrib-concat task.
It produces dist/css/sass.tmp, which you will need to process with the sass task:
sass: {
dist: {
files: [{
src: 'build/tmp.sass',
dest: 'dist/css/style.css'
}]
}
}
You would make sure they are run in sequence with something like this:
grunt.registerTask( 'default', ['concat', 'sass'] ); // add your uglify/cssmin here
However, I don't recommend this, because the order of the sass files is uncontrollable, and it won't make mixin's available, even if they are compiled to css first - which is pointless, because they loose their 'mixin' format. It's best to run sass on a single source file and import your other files in that source file.
Update
Regarding auto-loading of mixin files,
the SASS Reference does mention you can use custom importers (written in Ruby) that take care of #import; I'm not sure whether this is only for top-level importing of files, or also for #import mixin-name(foo) within rules, but I don't think so.
There is an alternative approach you could use, based on concat, assuming that you have one main sass file. You would need to add a single #import 'all-mixins' to it. This all-mixins.sass is a generated file:
concat: {
all_mixins: {
options: { separator: '\n' },
src: ['src/sass/mixins/*.sass'],
dest: 'build/all-mixins.sass'
}
}
And you would specify the sass option loadPath to add build/ to the path:
sass: {
dist: {
options: {
loadPath: 'build/'
},
files: [{
src: 'build/tmp.sass',
dest: 'dist/css/style.css'
}]
}
}
This is as close to auto-loading as it gets without extending sass itself.

Reference files from dynamic object

I am working on a Gruntfile, and am having difficulty getting a copy task to work the way I want.
I have an Uglify task defined using a dynamic file object like:
uglify: {
files: {
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}
}
This task works great, and I get my files written out as 'dst/some/path/file1.min.js' and 'dst/another/path/file2.min.js'.
I am working on a copy task, where I would like to copy the files I just built somewhere else. Rather than redefining the rule, I would like to reference the file set with a template.
If I use
copy: {
deploy: {
src: '<%= uglify.files %>',
dest: 'deploy/'
}
}
then I get the
Warning: Object # has no method 'indexOf'
error.
For various reasons beyond the scope of this question, globbing tricks won't work for the deploy.
So, in a copy task, how can I reference the set of files that another task just created?
You have files: {} as an object. It should be an array files: [].
uglify: {
files: [{
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}]
}
The src on copy config expected to be string or array, but you set an object on it, and when grunt tries to apply indexof method on the src of copy task, error will be the result. you can avoid this by setting uglify.files as array of objects, like this:
uglify: {
files: [{
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}]
}
Then, it will pass the error but you goal won't meet. you need to select dest of uglify as src for copy. the solution is the grunt method, TEMP FILES, you should set uglify dest in a temp path and then select what you need from there as src of copy task. something like this:
copy:{
deploy:{
files: [{
expand: true,
cwd: 'dst'
src: '**/*.min.js'
dest: 'deploy'
}]
}
}

Defining an array of only one object in YAML

I'm trying to use load-grunt-config to organise better my Grunt tasks.
So far I have had no issues with this. Now, I was trying to configure something like imagemin.
So, basically this is the structure I'm trying to replicate within YAML:
dynamic: { // Another target
files: [{
expand: true, // Enable dynamic expansion
cwd: 'src/', // Src matches are relative to this path
src: ['**/*.{png,jpg,gif}'], // Actual patterns to match
dest: 'dist/' // Destination path prefix
}]
}
And this is my attempt:
images:
files: [
expand: true
cwd: '<%= ui %>/img/'
src:
- '**/*.{png,jpg,gif}'
dest: '<%= dist %>/img'
]
However, something must be wrong as the plugin isn't able to get the correct data and hence, fails.
>> JS-YAML: missed comma between flow collection entries in "grunt/imagemin.yaml" at line 4, column 8:
>> cwd: '<%= ui %>/img/'
>>
Does anyone knows what could be wrong?
Brackets are only for in-line lists. Your list of files should look like this:
images:
files:
- expand: true
cwd: '<%= ui %>/img/'
src:
- '**/*.{png,jpg,gif}'
dest: '<%= dist %>/img'
You can test your YAML for correct syntax with an online parser like this one.

Copy all files from directory to another with Grunt.js copy

I'm trying to copy all the files in a directory to another directory as part of my build process. It works fine for individual files that I specify explicitly but when I try to copy the whole directory it does weird things like copies the full directory structure (or nothing at all). Here is the relevant part from my GruntFile.js:
copy: {
myvoice: {
files: [
{ src:"src/html/index.html", dest:"dist/myvoice/index.html" },
{ src:"src/html/css/style.css", dest:"dist/myvoice/css/style.css" },
{ src:"src/html/js/require.js", dest:"dist/myvoice/js/require.js" },
{ src:"build/myvoice/main.js", dest:"dist/myvoice/js/main.js" },
{ src:"src/html/css/fonts/*", dest:"dist/myvoice/css/fonts/" }
]
}
},
Specifically it's the last line that I can't get to work:
{ src:"src/html/css/fonts/*", dest:"dist/myvoice/css/fonts/" }
The flatten: true option as in this answer might work for some cases, but it seems to me that the more common requirement (as in my case) is to copy a folder and its sub-folder structure, as-is, to dest. It seems that in most cases if you have sub-folders, they are probably being referenced that way in code. The key to doing this is the cwd option, which will preserve folder structure relative to the specified working directory:
copy: {
files: {
cwd: 'path/to/files', // set working folder / root to copy
src: '**/*', // copy all files and subfolders
dest: 'dist/files', // destination folder
expand: true // required when using cwd
}
}
This task will maintain folder structure if you specify a file glob. What you want is the flatten option which will remove the structure.
{
expand: true,
flatten: true,
src: ['src/html/css/fonts/**'],
dest: 'dist/myvoice/css/fonts/',
filter: 'isFile'
}
Find the rest of the available options in the Github repo. Hope this helps.
I would like to add that changing the format of the glob in src will modify how the copy works.
As pointed out by bmoeskau above, the following will copy everything inside dist/ and move it to path/to/dir (overwriting the destination if it already exists).
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '**'
}
}
Note however, that:
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*'
}
}
Will only copy files inside dist/ as well as directories, but will not copy the contents of those directories to the destination.
Also, the following with src: '*/*' will only copy directories with contents inside dist/. That is, files just inside dist/ will not be copied.
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*/*'
}
}
Finally, same as above, but src: '**/**' will copy only files inside dist/ as well as files inside dist/ subdirectories to path/to/dir. So there will be no folders inside the destination.
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*/*',
flatten: true,
filter: 'isFile'
}
}
Had to use egdy instead curly braces for the files segment (in Coffeescript)...
copy: {
files: [
cwd: 'path/to/files'
src: '**/*'
dest: 'dist/files'
expand: true
]
}
If you are developing with angular yeoman , then this is the better way to copy with grunt.
expand: true is required when using cwd. <%= yeoman.app %> is just the app route ('.').
{
expand: true,
cwd: '<%= yeoman.app %>/data',
dest: '<%= yeoman.dist %>/data',
src: ['**']
}

Concat a single file to every file in a directory using grunt

Using Grunt, I want to concat one file to all of the files in a build directory. The purpose of doing so is to append (or potentially prepend) IE specific CSS files to a build CSS file.
To task this:
build/
file1.css
file2.css
file3.css
And create this:
build/
file1.css
file1.ie.css
file2.css
file2.ie.css
file3.css
file3.ie.css
I thought that the expand option might be what I was looking for but I can't figure out how to get it to do what I want.
Try the banner option in grunt-contrib-concat:
concat: {
dist: {
options: {
banner: '/* IE specific things here */',
},
expand: true,
cwd: 'build/',
ext: '.ie.css',
src: ['**/*.css'],
dest: 'build/',
},
},

Categories