I have several files named:
jquery.a.b.coffee
jquery.a.c.coffee
jquery.a.d.coffee
and they are all compiled into one jquery.js file in my output directory.
Although I guess this behavior might be nice in some cases, I would like to have them to compile into different files like jquery.a.b.js, jquery.a.c.js and so on. How can I tell grunt-contrib-coffeescript to do so?
My Gruntfile.js looks like this:
module.exports = function (grunt) {
grunt.initConfig({
coffee: {
dist: {
files: [{
expand: true,
flatten: true,
cwd: 'app/webroot/coffee',
src: ['{,*/}*.coffee'],
dest: 'app/webroot/js',
ext: '.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-coffee');
};
Thanks for your help!
The problem lies on the filenames having multiple dots.
If it was jquery-a-b.coffee, jquery-a-c.coffee etc, you would have seen the expected output.
It is a known issue (extension is after last period only) and grunt developers made this on purpose.
Here is a quote from one of them:
There's two ways ext could work; it could consider everything after
the first dot the extension, or everything after the last dot the
extension. We chose the former because the use-case is more common (we
encounter .min.js files all the time). That being said, you can use
the rename option to specify a function that will use whatever custom
naming logic you need.
So, the only workaround for now is to remove ext and use rename like this:
coffee: {
dist: {
files: [{
expand: true,
cwd: 'app/webroot/coffee',
src: ['{,*/}*.coffee'],
dest: 'app/webroot/js',
rename: function(dest, src) {
return dest + '/' + src.replace(/\.coffee$/, '.js');
}
}]
}
}
Update as of Grunt 0.4.3:
You can now use the extDot option along with ext
ext: '.js',
extDot: 'last'
This works so you don't have to add the files by hand in your gruntFile:
coffee: {
glob_to_multiple: {
expand: true,
flatten: true,
cwd: 'app/webroot/coffee/',
src: ['*.coffee'],
dest: 'app/webroot/',
ext: '.js'
}
},
cwd: the folder where your files are
src: the matching pattern for your files, using glob
dest: The folder where your files are going.
See https://github.com/gruntjs/grunt-contrib-coffee#usage-examples for some sample usages
Related
I feel like I must be missing something really simple here, but for all my searching and going over the docs, I just cannot find a solution to this problem.
I have an inherited file structure (which at the moment cannot change) that looks like this:
- Folder 1
-Web Files Folder
- Folder 2 (root)
- .eslintrc.js
Folder 1 and 2 are siblings of one another, my main set of js, jsx, ts and tsx are set up in the Web Files Folder, and my eslint and webpack configs, package.json and entry point files are all in Folder 2.
I cannot seem to get the IDE (in this case VS Code) to effectively lint the files within the Web Files Folder. I have tried a whole host of things, the latest of which was trying to use overrides in my .eslintrc.js file to point to the relevant directory:
module.exports = {
env: {
browser: true,
es6: true,
jest: true,
jquery: true,
node: true
},
extends: [
'eslint:recommended',
'eslint-config-prettier',
'plugin:#typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:jsx-a11y/recommended',
'prettier',
'prettier/#typescript-eslint'
],
parser: '#typescript-eslint/parser',
parserOptions: {
jsx: true,
ecmaVersion: 2020
},
plugins: ['#typescript-eslint', 'react', 'prettier', 'jsx-a11y', 'jest'],
root: true,
rules: {
'array-callback-return': 0,
'consistent-return': 0,
...
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
},
react: {
version: 'detect'
}
}
overrides: [
{
files: ['../Folder 1/Web Files Folder/*.js', '../Folder 1/Web Files Folder/*.jsx', '../Folder 1/Web Files Folder/*.ts', '../Folder 1/Web Files Folder/*.tsx']
},
]
};
This results in the error in the Eslint console: Invalid override pattern (expected relative path not containing '..')
However nothing I have tried works. I am not worried about the linting in the build, only getting the errors to appear in the IDE and resolve on save (which works perfectly if I place the files within Folder 2)
I am looking for a solution which I can use in my eslintrc.js file rather than any changes to settings in the IDE if possible. Something like
project: ['./**/*', '../Folder 1/Web Files Folder/**/*']
I have a gruntfile that compiles my jekyll for me, and I want it to push the compiled folder up to my github and ignore the main folder that Gruntfile resides in. I'm doing this utilizing grunt git-deploy. I'm getting "Arguments to path.join must be strings. Use --force to continue". But everything is in a string as it's suppose to be and is documented, unless I'm missing something which is quite possible because I haven't slept in a day or so.
Here is the portion in question
git_deploy:
your_target:
options:
url: 'git#github.com:Diope/diope.github.io.git'
message: 'new post'
src: "/_site"
Any direction is greatly appreciated.
The example from grunt git-deploy is:
grunt.initConfig({
git_deploy: {
your_target: {
options: {
url: 'git#github.com:example/repo.git'
},
src: 'directory/to/deploy'
},
},
})
Have you tried wrapping with braces and using the single quotes for the src?
git_deploy: {
your_target: {
options: {
url: 'git#github.com:Diope/diope.github.io.git'
},
src: '/_site'
},
},
After waking up from a long overdue siesta, I noticed the problem immediately. I had a leading "/" for my source location.
This is what I currently have:
coffee: {
options: {
bare: true
},
glob_to_multiple: {
expand: true,
flatten: false,
cwd: 'public/js',
src: ['*.coffee'],
dest: 'public/js',
ext: '.js'
}
},
The problem is I have two directories which contain my JS files, and I don't know how to set it up to watch both places, and compile the javascript into the same directories the coffeescripts are in.
This is the coffeescript command I'm trying to replicate the functionality of: coffee --watch --compile .
if I understand it correctly and you want to compile coffee into JS from two directories, there are two simple solutions for you.
First solution - compile JS file to the same directory as the original CoffeeScript file:
coffee:
options:
bare: true
compile:
files: [
expand: true
src: ['js/**/*.coffee', 'other/**/*.coffee']
dest: './'
ext: '.js'
]
Second solution - compile JS file to the common directory for all coffee files.. (but it keeps the relative path, so if you have coffee/hello.coffe it is going to be placed into js/coffee/hello.js
coffee:
options:
bare: true
compile:
files: [
expand: true
src: ['js/**/*.coffee', 'other/**/*.coffee']
dest: 'js/'
ext: '.js'
]
Hope it helps, otherwise you can try different settings for each directory as follows:
coffee:
options:
bare: true
compileOneDir:
#...
compileSecondDir:
#...
I am trying to write a grunt task to compile numerous .coffee files to corresponding .js files and .map files using grunt. I have the grunt coffee plugin, but there are some problems:
It compiles all files into one common destination folder instead of keeping the .js files in same folder as the .coffee file.
It merges two .coffee files of the same name in different directories into one file in the destination directory.
Please help solving these:
Grunt plugin: https://www.npmjs.org/package/grunt-contrib-coffee
Gruntfile.coffee:
module.exports = (grunt) ->
grunt.initConfig(
pkg: grunt.file.readJSON 'package.json'
coffee:
coffee_to_js:
options:
bare: true
sourceMap: true
expand: true
flatten: true
cwd: "client"
src: ["**/*.coffee"]
dest: 'client'
ext: ".js"
)
#Load Tasks
grunt.loadNpmTasks 'grunt-contrib-coffee'
grunt.registerTask('compile', ['coffee']);
null
Compiled Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
coffee: {
coffee_to_js: {
options: {
bare: true,
sourceMap: true
},
expand: true,
flatten: true,
cwd: "client",
src: ["**/*.coffee"],
dest: 'client',
ext: ".js"
}
}
});
grunt.loadNpmTasks('grunt-contrib-coffee');
grunt.registerTask('compile', ['coffee']);
return null;
};
File structure before compile:
File structure after compile:
Compilation message:
If you want to maintain the structure of where your JS is compiled, you should set the flatten flag to false. See Grunt Configuring tasks - Building the files object dynamically.
module.exports = (grunt) ->
grunt.initConfig
pkg: grunt.file.readJSON 'package.json'
coffee:
coffee_to_js:
options:
bare: true
sourceMap: true
expand: true
flatten: false
cwd: "client"
src: ["**/*.coffee"]
dest: 'client'
ext: ".js"
#Load Tasks
grunt.loadNpmTasks 'grunt-contrib-coffee'
grunt.registerTask 'compile', ['coffee']
This is the output when not flattened which I believe is what you're after:
$ grunt compile
Running "coffee:coffee_to_js" (coffee) task
File client/main.js created.
File client/main.js.map created (source map).
File client/models/question.js created.
File client/models/question.js.map created (source map).
File client/views/question.js created.
File client/views/question.js.map created (source map).
My project has over 300 CoffeeScript files, so it takes several seconds to recompile everything. I'd like to only recompile the changed CoffeeScript files.
Here's the closest I've come so far, but the "frontend-src/coffeescript" folder structure is being copied from the src directory to the dest directory.
coffee: {
changed: {
expand: true,
cwd: './',
src: ['<%= grunt.regarde.changed %>'],
dest: 'public/js/',
ext: '.js'
}
},
regarde: {
coffee: {
files: 'frontend-src/coffeescript/**/*.coffee',
tasks: ['coffee:changed', 'livereload']
}
}
This is all with Grunt 0.4.0. Any help would be greatly appreciated!
I had this issue myself and I was able to come up with a solution for it inspired by the comments on this issue:
https://github.com/gruntjs/grunt-contrib-watch/issues/14
It is actually for the grunt-contrib-watch plugin, but it should also work for grunt-regarde, as it has similar events.
The idea is to bind a callback the watch event, in which you add a new task to the grunt configuration with the changed file's path, then run it.
From my Gruntfile.coffee:
coffee:
app:
expand: true
cwd: 'app/'
src: ['*.coffee',"**/*.coffee"]
dest: './public/temp'
ext: '.js'
watch:
coffee:
files: ['app/**/*.coffee']
tasks: ['livereload']
options:
nospawn: true
grunt.event.on 'watch', (action, filepath) ->
cwd = 'app/'
filepath = filepath.replace(cwd,'')
grunt.config.set('coffee',
changed:
expand: true
cwd: cwd
src: filepath
dest: './public/temp'
ext: '.js'
)
grunt.task.run('coffee:changed')
The nospawn is important for the watch task, so it runs the new task before the livereload task. I am pretty sure regarde does not spawn child processes by default.
I've had the same issue. I solved it using the regarde:file event.
First I listen for changed files by using the regarde:file event. This will feed the configuration for two tasks: clean:coffee if files in the source location has been deleted and coffee:refresh if files have been changed/added.
Then the regarde task will trigger its tasks, which will launch refresh:coffee (not to be mistaken from coffee:refresh). This task will check if there is configuration added for clean:coffee and/or for coffee:refresh and run these tasks if needed (via function grunt.task.run). If will also reset the flag, which will cause the next received regarde:file event to cleanup the configuration again.
In depth explanation:
First of all, regarde config:
// watch for changed coffeescript files
coffee: {
files: 'path/to/coffee/**/*.coffee',
tasks: ['refresh:coffee', 'livereload']
},
Then I listen for the regarde:file event, where I update the clean:coffee and coffee:refresh file lists in their config.
Feed the configuration based on the regarde:file event:
grunt.event.on('regarde:file', function (status, target, filepath) {
if (resetFlag) {
// clean file list from previous cycle, so clean clean:coffee and coffee:refresh
// file lists
...
resetFlag = false;
}
if (status === 'deleted') {
if (filepath) {
// calculate filepath's destination and
// add it to clean:coffee filelist
}
} else {
if (!grunt.file.isDir(filepath)) {
// add filepath to coffee:refresh filelist
}
}
}
It is easy to update configuration via grunt.config() function. Below the code snippets to feed coffee:refresh and clean:coffee.
Adding config to coffee:refresh:
var config = grunt.config('coffee') || {};
var value = config.refresh || {};
value.files = value.files || [];
...
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.files.push({
expand:true,
src:src,
dest:dest,
cwd:cwd,
ext:'.js'
});
grunt.config('coffee', config);
Adding config to clean:coffee:
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.src.push(path.join(dest, src.replace('coffee', 'js')));
// clean only what has been removed
config = grunt.config('clean') || {};
config.coffee = value;
grunt.config('clean', config);
Task refresh:coffee gets triggered:
grunt.registerMultiTask('refresh', 'refreshing the changed file(s)', function () {
this.requires('regarde');
var tasks = [];
var clean = grunt.config('clean');
// check if there is clean:refresh config available
if (clean && clean[this.target]) {
tasks.push('clean:' + this.target);
}
var config = grunt.config(this.target);
// check if there is coffee:refresh config available
if (config && config.refresh) {
tasks.push(this.target + ':refresh');
}
// run the tasks
grunt.task.run(tasks);
// set the resetFlag back to true
resetFlag = true;
});
grunt.regarde.changed is an array correct?
Should src: ['<%= grunt.regarde.changed %>']
be src: '<%= grunt.regarde.changed %>'
I looked through grunt-contrib-coffee's source for a second to see if it could be not correctly handling whatever you're giving it. Looked kind of likely that the stringified array you're giving it, doesn't get caught and dealt with.
I think what you're passing accidentally may be: src: [ '[path1, path2, path3, etc]' ]
If I'm way off base, leave a comment and I'll delete this answer.