Switch output folder based on filename in gulp task - css

I have different *.scss files in my src folder and I want one file to be compiled in its own separate folder.
Lets assume I have the files normalFile_1.scss, specialFile.scss, normalFile_2.scss. I want the two normal files to be compiled to the folder Public/Css, the special file however should end up in the folder Public/Css/Special.
I have tried to get the current filename in the task with gulp-tap, which works fine.
.pipe($.tap(function (file, t) {
filename = path.basename(file.path);
console.log(filename); //outputs normalFile_1.css, specialFile.css, normalFile_2.css
}))
And with gulp-if I then wanted to switch the output folder based on the filename variable (PATHS.dist is the output "root" folder Public):
.pipe($.if(filename == 'specialFile.css', gulp.dest(PATHS.dist + '/Css/Special'), gulp.dest(PATHS.dist + '/Css')));
But everything still ends up in the Public/Css folder. Why does this not work? Is this even a good way of trying to accomplish that or are there better methods?

There are two ways to do this shown below:
var gulp = require("gulp");
var sass = require("gulp-sass");
var rename = require("gulp-rename");
var path = require('path');
gulp.task('sass', function () {
return gulp.src('src/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(rename(function (path) {
if (path.basename == "specialFile") {
path.dirname = "Special";
}
}))
.pipe(gulp.dest('Public/Css'))
// .pipe(gulp.dest(function(file) {
// var temp = file.path.split(path.sep);
// var baseName = temp[temp.length - 1].split('.')[0];
// console.log(baseName);
// if (baseName == "specialFile") {
// return 'Public/Css/Special';
// }
// else return 'Public/Css';
// }))
});
gulp.task('default', ['sass']);
Obviously I suggest the rename version.
[Why a simple file.stem or file.basename doesn't work for me in the gulp.dest(function (file) {} version I don't know - that would certainly be easier but I just get undefined.]

Related

Gulp-less watcher breaks when a less error is encountered in a file

I want to watch a folder of less files. When one of them is changed, I want to compile only the "styles.less" file (this file contains #imports to the rest of the files like "header.less", "navigation.less", etc.)
For this, I created 2 tasks. When I run the task "watchless", everything is ok, it compiles the styles.less to styles.css. But if an error is encountered, when I edit a less file, the watcher breaks, even with gulp-plumber. How can I fix this?
var gulp = require('gulp');
var plumber = require('gulp-plumber');
var less = require('gulp-less');
var watch = require('gulp-watch');
var path_less = 'templates/responsive/css/less/';
var path_css = 'templates/responsive/css/';
gulp.task('less2css', function () {
return gulp.src(path_less + 'styles.less')
.pipe(plumber())
.pipe(less())
.pipe(gulp.dest(path_css))
});
gulp.task('watchless', function() {
gulp.watch(path_less + '*.less', ['less2css']); // Watch all the .less files, then run the less task
});
Finally, it worked, using the following code:
var gulp = require('gulp');
var gutil = require('gulp-util');
var less = require('gulp-less');
var watch = require('gulp-watch');
var path_less = 'templates/responsive/css/less/';
var path_css = 'templates/responsive/css/';
gulp.task('less2css', function () {
gulp.src(path_less + 'styles.less')
.pipe(less().on('error', gutil.log))
.pipe(gulp.dest(path_css))
});
gulp.task('watchless', function() {
gulp.watch(path_less + '*.less', ['less2css']); // Watch all the .less files, then run the less task
});

Laravel Elixir: Use wildcard without combining

I have a folder, in resources/assets/sass that have 2 files 1.scss and 2.scss
I would want to do:
elixir(function (mix) {
.sass('*.scss', './public/css/');
});
And for that to generate 1.css and 2.css
I actually have more than 2 files and that's why I don't want to write them one by one. Any way to accomplish this? Thanks
Since you can write any JavaScript in the Gulpfile, you can use the 'glob' module to get the filenames, like this:
var elixir = require('laravel-elixir');
var glob = require('glob');
var path = require('path');
elixir(function (mix) {
for (let file of glob.sync('resources/assets/sass/*.scss')) {
mix.sass(path.basename(file), './public/css/');
}
});
It can be more advanced if needed - e.g. I'm using it with versioning and custom paths (and ES2015 syntax):
const elixir = require('laravel-elixir');
const glob = require('glob');
const path = require('path');
elixir(mix =>
{
let build_files = [];
for (let theme of glob.sync('resources/assets/sass/themes/*/')) {
theme = path.basename(theme);
mix.sass(`themes/${theme}/app.scss`, `public/css/${theme}/app.css`);
build_files.push(`css/${theme}/app.css`);
}
mix.version(build_files);
});

Using Sourcemaps with google chrome

i have tried to configure sourcemaps in less files. When I inspect an Element I see the correct less file with the file extension. So it seems to work
But when I do changes the file name for Example style.less:1120 change to style.css:129
What went wrong?
Another problem is, that chrome shows me only the style.less file. This file imports only my components. So instead of seeing component.less:10 i see style.less:221
My gulpfile:
var gulp = require('gulp');
var less = require('gulp-less');
var rename = require('gulp-rename');
var sourcemaps = require('gulp-sourcemaps');
var paths = {
scripts: ['client/js/**/*.coffee', '!client/external/**/*.coffee'],
images: 'client/img/**/*',
less: 'web/style/style.less'
};
gulp.task('less' , function() {
// Minify and copy all JavaScript (except vendor scripts)
// with sourcemaps all the way down
return gulp.src(paths.less)
.pipe(sourcemaps.init())
.pipe(less())
.pipe(rename(function(path) {
path.extname = ".css";
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest('web/style/.'));
});
// Rerun the task when a file changes
gulp.task('watch', function() {
gulp.watch(paths.less, ['less']);
});
// The default task (called when you run `gulp` from cli)
gulp.task('default', ['watch']);

How to avoid unnecessary uglifying in GruntJS?

I have a grunt file with the following definition:
uglify: {
build: {
src: 'www/temp/application.js', // a concatenation of files via grunt-contrib-concat
dest: 'www/temp/application.min.js'
}
},
what I would really like to do is to recompute the final application.min.js only in case that application.js file was changed. More precisely, I want to add the condition:
# pseudocode
if (getFileContents(application.js) == getFileContents(previously.uglified.application.js)) {
// do nothing
} else {
// run uglifying on application.js
}
Reason:
I deploy my project by git and uglifying is relatively slow (3+ seconds) and moreover, it is unnecessary since I don't change JS files often.
There are several possible solutions:
You can create your own grunt task that will check files for last modify time using for example fs.stat then run uglify task through grunt.task.run with prepared options as argument.
Or you can build files object dynamically passing it through filter function:
var fs = require('fs');
module.exports = function (grunt) {
function filterChanged(files) {
var mtime = '',
stats;
for (var dest in files) {
stats = fs.statSync(files[dest]);
try {
mtime = fs.readFileSync(files[dest] + '.mtime', 'utf8');
}
catch (ex) {
fs.writeFileSync(files[dest] + '.mtime', stats.mtime, 'utf8');
return files;
}
if (stats.mtime == mtime || !mtime) {
delete files[dest];
}
else {
fs.writeFileSync(files[dest] + '.mtime', stats.mtime, 'utf8');
}
}
return files;
}
grunt.initConfig({
uglify: {
build: {
files: filterChanged({
'www/temp/application.min.js': 'www/temp/application.js'
})
}
}
});
};
This causes invoke of filterChanged function every time uglify task runs.

Can GruntJS fetch external files?

For example I have index.css that contains links to another css files:
#import "http://<some_url>/bootstrap.css";
#import "http://<some_url>/plugin.css";
#import "app.css";
It is possible to concatenate these files with Grunt JS?
Looking at the Grunt API, the file stuff appears to apply exclusively to local files.
http://gruntjs.com/api/grunt.file
Furthermore I haven't seen anything in the source code where it parses CSS files looking for imports.
To get them concatenated together:
I'd recommend that you download the files locally, put them in your usual css folder then use Grunt concat as normal.
I'd then write a small script using wget to download fresh copies of these dependencies before building with grunt.
I know it's been a while since this was asked, but I came across it while trying to do something similar. Here is one way to save a file from a url using a grunt task.
module.exports = function(grunt) {
'use strict';
var http = require('http');
grunt.initConfig({
watch: {
scripts: {
files: ['**/*.cfc'],
tasks:['saveURL']
}
},
open:{
error:{
path:'http://<server>/rest/error.html'
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-open');
grunt.registerTask('default', ['watch']);
grunt.registerTask('saveURL', 'Write stuff to a file', function() {
var done = this.async();
var reloadurl = 'http://<server>/rest/index.cfm?rl';
grunt.log.writeln('Loading URL:' + reloadurl + ' ...');
http.get(reloadurl, function(res) {
var pageData = "";
if(res.statusCode != '200'){
//if we don't have a successful response queue the open:error task
grunt.log.error('Error Reloading Application!: ' + res.statusCode);
grunt.task.run('open:error');
}
res.setEncoding('utf8');
//this saves all the file data to the pageData variable
res.on('data', function (chunk) {
pageData += chunk;
});
res.on('end', function(){
//This line writes the pageData variable to a file
grunt.file.write('error.html', pageData)
done();
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
done(false);
});
});
};

Resources