My middleman template has an 'id' variable that I put my html emails job name into.
I know if I change my middleman erb file from index.html.erb to newName.html.erb it will output that as the final files name.
My problem is that most of my grunt tasks require the file name I want them to run on (I've tried using *.html, but it only works for some tasks) and short of editing that in the grunt file prior to starting grunt up they won't execute if I change the erb file name.
Is there a way to pass grunt that 'id' variable to name the file middleman is outputting and also plug that variable into the various tasks so they too accept that as what the filename?
Here is my grunt config:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Build html
middleman: {
options: {
useBundle: true
},
server: {},
build: {
options: {
command: "build"
}
}
},
// Format html file
prettify: {
options: {
// Task-specific options go here.
},
one: {
src: 'build/index.html',
dest: '_output/index.html'
}
},
// Run the text converter
execute: {
simple_target_with_args: {
options: {
// execute node with additional arguments
args: ['_output/index.html']
},
src: ['node_modules/node-text-converter/converter.js']
}
},
'special-html': {
compile: {
files: {
'_output/index.html': '_output/index.html',
}
}
},
'phantomjs_screenshot': {
main: {
options: {
delay: 1000
},
files: [{
expand: true,
cwd: '_output',
src: ['**/*.html'],
dest: '_output/screenshots/',
ext: '.jpg'
}]
}
}
});
You should store your variable in a JSON file and import it both into Middleman and Grunt.
Related
I'm working on a grunt script to copy some files from 'dev' into 'dist' and modify the folder structure slightly. There are html files present inside dev/html/eas1/ and dev/html/eas2. The script uses grunt.config.set in order to change the src and dest locations of the copy and the script is running without errors, but nothing is being copied over. Can anyone help?
module.exports = function(grunt) {
grunt.initConfig({
projectCodes: {
eas: ['eas1', 'eas2', 'eas3', 'eas4', 'eas5', 'eas6']
},
copy: {
main: {
files: [{
expand: true,
src: 'dev/eas/html/eas1/*',
dest: 'dist/eas/eas1/html/',
filter: 'isFile'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('dev', function(p) {
var projectCodes = grunt.config.get('projectCodes');
for(code in projectCodes[p]) {
grunt.config.set('copy.main.files.0.src', 'dev/'+p+'/html/'+projectCodes[p][code]+'/*');
grunt.config.set('copy.main.files.0.dest', 'dist/'+p+'/'+projectCodes[p][code]+'/html/');
grunt.task.run('copy:main');
}
});
};
I've done a fair bit of searching but can't seem to come up with a full answer to this.
I'm using grunt to manage my sass flow and I've been trying to find a way to output multiple css styles from grunt.
For example:
base.scss should have two outputs the first being style.css which has the expanded css style.
The second should be style.min.css which has the compressed css style.
How can I configure my gruntfile to do this for me?
You can do this by having two configurations, one outputting expanded CSS and the other compressed. Then register your task to run both. Your grunt file should look something like this:
Example
module.exports = function(grunt) {
'use strict';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Sass
sass: {
dev: { // This outputs the expanded css file
files: {
'style.css': 'base.scss'
}
},
prod: { // This outputs the compressed css file
options: {
outputStyle: 'compressed' // Minify output
},
files: {
'style.min.css': 'base.scss'
}
}
}
});
grunt.registerTask('default', ['sass:dev', 'sass:prod']); // Task runs both
}
Here is a more complete solution of what belongs in gruntfile.js, improving upon what Colin Bacon has already posted. By default grunt's pkg is already set to read package.json in the current directory, so no need to write that. You just need to install the jit-grunt plugin (besides the watch and sass plugins of course) to get my answer working.
module.exports = function(grunt) {
require('jit-grunt')(grunt);
grunt.initConfig({
sass: {
expanded: { // Target
options: { // Target options
style: 'expanded'
},
files: { // Dictionary of files
'style.css': 'style.scss' // 'destination': 'source'
}
},
compressed: { // Target
options: { // Target options
style: 'compressed'
},
files: { // Dictionary of files
'style.min.css': 'style.scss' // 'destination': 'source'
}
}
},
watch: {
styles: {
files: ['**/*.scss'], // which files to watch
tasks: ['sass'],
options: {
spawn: false // speeds up watch reaction
}
}
}
});
grunt.registerTask('default', ['sass', 'watch']);
};
Just add a new manifest file in your styles folder. For example, you have normally main.scss, if you create main2.scss and import some files in there. It will create a file for each manifest file you have.
If your sass task looks something like this (default yeoman webapp generator):
sass: {
options: {
sourceMap: true,
includePaths: ['bower_components']
},
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/styles',
src: ['*.{scss,sass}'],
dest: '.tmp/styles',
ext: '.css'
}]
},
server: {
files: [{
expand: true,
cwd: '<%= config.app %>/styles',
src: ['*.{scss,sass}'],
dest: '.tmp/styles',
ext: '.css'
}]
}
}
The file section sass read all .scss/.sass files and copy those to .tmp/styles. Later, copy task move those to dist/styles.
my task is the following:
htmlmin : {
dist : {
options : {
removeComments : true,
collapseWhitespace : true
},
files : {
'index.html' : 'index-src.html'
}
}
},
this works fine when i have just one html file on my site, so this processes index-src.html into minified index.html.
what if i have 100 other html files to process? i don't want to manually list them in my gruntfile.
how can i abstract the file name and tell grunt to minify my src file to the corresponding production file? in my case they are:
source file is [name]-src.html
production file is [name].html
i'm guessing it's just a matter of syntax, but i don't know what to write.
thanks! :)
See the Globbing Patterns section of the Grunt Documentation.
I believe you'll just have to change your param files object to:
'index.html' : '*-src.html'
Update
Re-reading your question, I realized you needed a 1-1 file conversion for dynamic source and destination file names.
For that see Building the files object dynamically
I have yet to use this in my project but the syntax looks straight forward. You may need to change your src vs production naming convention to a folder based convention.
/source/name.html (source folder)
/build/name.html (destination folder)
Example
files: [
{
expand: true, // Enable dynamic expansion.
cwd: 'source/', // Src matches are relative to this path.
src: ['*-src.html'], // Actual pattern(s) to match.
dest: 'build/', // Destination path prefix.
ext: '.html', // Dest filepaths will have this extension.
extDot: 'first' // Extensions in filenames begin after the first dot
}
]
module.exports = function (grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
controlCss: {
src: ['UI.controls/assets/css/*.css'],
dest: 'UI.controls/assets/css/min/production.css'
},
controlJs: {
src: ['UI.controls/assets/js/*.js'],
dest: 'UI.controls/assets/js/min/production.js'
},
coreJs: {
src: ['UI.core/assets/js/*.js'],
dest: 'UI.core/assets/js/min/production.js'
},
dist: {
src: ['UI.controls/assets/templates/*.htm'],
dest: 'UI.controls/assets/templates/min/production.min.htm'
}
},
cssmin: {
controlCss: {
src: 'UI.controls/assets/css/min/production.css',
dest: 'UI.controls/assets/css/min/production.min.css'
}
},
uglify: {
controlJs: {
src: 'UI.controls/assets/js/min/production.js',
dest: 'UI.controls/assets/js/min/production.min.js'
},
coreJs: {
src: 'UI.core/assets/js/min/production.js',
dest: 'UI.core/assets/js/min/production.min.js'
}
},
htmlmin: {
dist: {
options: {
removeComments: true,
collapseWhitespace: true
},
expand: true,
cwd: 'build',
src: ['UI.controls/assets/templates/*.htm'],
dest: 'UI.controls/assets/templates/min/production.min.htm'
}
}
});
// 2. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-htmlmin');
// 3. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'cssmin', 'uglify', 'htmlmin']);
};
I have a JavaScript file called toInject.js. I would like the contents of this file to be injected into another JavaScript file in the place of a comment placeholder /* === toInject.js placeholder === */ through a grunt task. What grunt task is available to do this any what configuration is required?
Both files before grunt task has run:
toInject.js
alert('hello world');
myScript.js
function doSomething() {
/* === toInject.js placeholder === */
}
Changes to myScript.js after grunt task has run:
myScript.js
function doSomething() {
alert('hello world');
}
You can dynamicly set task configs:
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-replace');
grunt.initConfig({
replace: {
dist: {
options: {
patterns: [{
match: 'foo',
replacement: 'bar'
}]
},
files: [
{expand: true, flatten: true, src: ['src/index.html'], dest: 'build/'}
]
}
}
});
// register custom task
grunt.registerTask('replaceByFileContents', 'Description', function() {
// get files
grunt.file.expand({cwd: 'src', '**/*.js'}).map(function(file) {
// set config: replace 'index.js' by index.js content
grunt.config.set('replace.dist.option.patterns', {
match: file,
replacement: grunt.file.read(file)
});
// run task
grunt.task.run(replace:dist)
})
});
My grunt.js has a typical minification task:
min: {
dist: {
src: ['dist/precook.js'],
dest: 'dist/precook.min.js'
}
}
What is the simplest way to have multiple dest files? I'd like to minify into:
dist/precook.min.js
example/js/vendor/precook.min.js
The built-in min task doesn't appear to support multiple destinations, so I assume this can be achieved via a simple "copy" task. Can someone please point me in the right direction?
I'd use grunt-contrib-copy plugin:
Install with npm:
npm install grunt-contrib-copy
Modify grunt.js (add copy task definition and load copy plugin):
...
copy: {
dist: {
files: {
'example/js/vendor/': 'dist/precook.min.js'
}
}
}
...
grunt.loadNpmTasks('grunt-contrib-copy');
Optionally register copy in to grunt's default task.
The added beauty here is that you can now perform all other copy tasks as well. Even patterns are supported, like copy all minified files ('dist/*.min.js').
concat: {
css: {
src: ['UI.controls/assets/css/*.css'],
dest: 'UI.controls/assets/css/min/production.css'
},
js: {
src: ['UI.controls/assets/js/*.js'],
dest: 'UI.controls/assets/js/min/production.js'
},
js2: {
src: ['UI.core/assets/js/*.js'],
dest: 'UI.core/assets/js/min/production.js'
}
},
cssmin: {
css: {
src: 'UI.controls/assets/css/min/production.css',
dest: 'UI.controls/assets/css/min/production.min.css'
}
},
uglify: {
js: {
src: 'UI.controls/assets/js/min/production.js',
dest: 'UI.controls/assets/js/min/production.min.js'
},
js2: {
src: 'UI.core/assets/js/min/production.js',
dest: 'UI.core/assets/js/min/production.min.js'
}
},
watch: {
css: {
files: ['UI.controls/assets/css/*.css'],
tasks: ['concat:css', 'cssmin:css']
},
js: {
files: ['UI.controls/assets/js/*.js'],
tasks: ['concat:js', 'uglify:js']
},
js2: {
files: ['UI.core/assets/js/*.js'],
tasks: ['concat:js', 'uglify:js']
}
}
This is an alternative approach (next to #jalonen's solution) which may to interesting to you, IF you are using requirejs to modularize your project, then you can use the requirejs optimizer to minify your modules.
First of all, you need to add grunt-contrib-requirejs to your project:
npm install grunt-contrib-requirejs --save-dev
Grunt configuration:
requirejs: {
production:{
options:{
// don't include libaries when concatenating/minifying
paths:{
angular:'empty:',
jquery:'empty:'
},
baseUrl:'path/to/src/js',
dir:'path/to/target/js',
// keeps only the combined files
removeCombined:true,
modules:[
{name:'app', exclude: ['moduleA', 'moduleB']},
{name:'moduleA'},
{name:'moduleB'}
]
}
}
}
...
grunt.loadNpmTasks('grunt-contrib-copy');
Explanation:
Let's say you have this dependency tree (-> means depends on):
app -> moduleA -> moduleA1
-> moduleA2
app -> moduleB -> moduleB1
-> moduleB2
After minifying you will have three files:
app (minified version of app)
moduleA (minified version of moduleA, moduleA1, and moduleA2)
moduleB (minified version of moduleB, moduleB1, and moduleB2)
Had a similar problem and created a grunt multi-task that runs a list of specified tasks on multiple directories
Usage for the exact case:
```
min: {
dist: {
src: ['dist/precook.js'],
dest: 'dist/precook.min.js'
}
},
multidest: {
minifiedFiles: {
tasks: ['min'],
dest: [
'dist/precook.min.js',
'example/js/vendor/precook.min.js'
]
}
}
```