Gulp: concatenate a file to each separate sass process - gulp

I wrote a gulp task to process all scss files in one folder into separate css files.
gulp.task('process', function () {
gulp.src(['./base.scss', './layout/*.scss'])
.pipe(sass())
.pipe(gulp.dest('dist'))
});
Now I want to concatenate one file (base.scss) to each scss process; how can I do this?

This should help you but I didn't test it. Gulp-foreach is good for you, it will treat each file from gulp.src as its own stream which you can manipulate separately. The code below then appends your base.scss to each stream, then concatenates them and then they go through the sass pipe.
var foreach = require('gulp-foreach');
var concat = require('gulp-concat');
var addsrc = require('gulp-add-src');
gulp.task('default', function () {
return gulp.src('./layout/*.scss')
// treats each file in gulp.src as a separate stream
.pipe(foreach(function (stream, file) {
return stream
// append or prepend
.pipe(addsrc.append('./base.scss'))
// you do have access to the 'file' parameter here if you need to rename
.pipe(sass())
.pipe(concat(path.basename(file.path)))
.pipe(gulp.dest('dist'));
}));
});
Let me know if it works for you.

Related

Check if file contains a specific string in GULP

I am attempting to use GULP4 to compress a series of HTML and PHP files. A problem I am running into is some of the files contain a <pre> tag. I do not want to compress those files because it would mess up that file. Is there a way using GULP I can evaluate if a file contains the string <pre> and if it does, avoid running compression on that file?
Here is my relevant code:
const gulp = require('gulp');
const {src, series, parallel, dest} = require('gulp');
const GulpReplace = require('gulp-replace');
function no_2_spaces_purchasingdemand_php()
{
console.log("no 2 spaces purchasingdemand_php")
return gulp.src
(
'dist/purchasingdemand/**/*.php'
, { base: "./" }
)
.pipe
(
GulpReplace(' ','☺☻')
)
.pipe
(
GulpReplace('☻☺','')
)
.pipe
(
GulpReplace('☺☻',' ')
)
.pipe(gulp.dest('./'))
}
exports.default = series(no_2_spaces_purchasingdemand_html)
I don't know what you are using to compress files, but here is a general example:
const gulp = require('gulp');
const filter = require('gulp-filter');
const minify = require('gulp-htmlmin');
gulp.task("preFilterTask", function () {
// return true if want the file in the stream
const preFilter = filter(function (file) {
let contents = file.contents.toString();
return !contents.match('<pre>');
});
return gulp.src("./*.html")
.pipe(preFilter)
.pipe(minify({ collapseWhitespace: true }))
.pipe(gulp.dest('filtered'));
});
gulp.task('default', gulp.series('preFilterTask'));
gulp-htmlmin by itself - for html files only - will not minify the <pre>...</pre> portion of an html file. So if you use gulp-htmlmin for html minification, you don't need to filter out those with <pre> tags.
I still showed how to filter based on file content using the gulp-filter plugin. It can access each file's contents. Return false from the filter function if you do not want that file to pass to the next pipe.

How can I use gulp to replace a string in a particular source file using a config object?

How to achieve a replacing a string on a particular source file while the source files will be concatenated.
var gulp = require('gulp'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
replace = require('gulp-replace');
var config = {
cssConcatFiles: [
'one.css',
'two.css',
'three.css'
]
};
gulp.task('css-concat', function() {
return gulp.src(config.cssConcatFiles)
.pipe(replace('url\(\'', 'url\(\'../images/fancybox/'))
// I want to perform this replace to a particular file which is "two.css"
.pipe(concat('temp.css'))
.pipe(uglyfycss())
.pipe(rename('temp.min.css'))
.on('error', errorLog)
.pipe(gulp.dest('public/css/plugins/fancybox'));
});
This should work. gulp-if
const gulpIF = require('gulp-if');
gulp.task('css-concat', function() {
return gulp.src(config.cssConcatFiles)
//.pipe(replace('url\(\'', 'url\(\'../images/fancybox/'))
// I want to perform this replace to a particular file which is "two.css"
.pipe(gulpIF((file) => file.path.match('two.css') , replace('url\(\'', 'url\(\'../images/fancybox/')))
.pipe(concat('temp.css'))
.pipe(uglyfycss())
.pipe(rename('temp.min.css'))
.on('error', errorLog)
.pipe(gulp.dest('public/css/plugins/fancybox'));
});
You could use the following pipe instead of the gulp-if call:
.pipe(replace(/url\(\'/g, function(match) {
if (this.file.relative === "two.css") {
return 'url\(\'../images/fancybox/';
}
else return match;
}))
since gulp-replace will take a function as an argument and provide that function with a vinyl file reference (this.file) which you can use to test for which file is passing through the stream. You must, however, return something from the function call even when you want to do nothing - so return the original match.
I recommend using gulp-if, much cleaner in your case.

Gulp: copy file to multiple folders starting with specific string

I'm working to copy a file style.scss from specific directory to multiple folders that start with skin-.
In fact, i don't know how to tell gulp to choose folders that start with this string skin-.
Here is my gulp code:
// Copy Files
gulp.task( "copyFiles" , function() {
return gulp.src( "app/scss/style.scss" )
.pipe( gulp.dest( "app/scss/skins/skin-*" ) );
});
At command prompt, it says that the task is running but with no result.
I have searched a lot around for that, but i didn't find a method. I found this question here which near to my question context, but it didn't help! Gulp copy single file (src pipe dest) with wildcarded directory
Modifying only slightly #davidmdem's answer at saving to multiple destinations:
const gulp = require("gulp");
const glob = require("glob");
const destinationFolders = glob.sync("app/scss/skins/skin-*");
gulp.task('copyFiles', function () {
var stream = gulp.src("app/scss/style.scss");
destinationFolders.forEach(function (skinFolder) {
stream = stream.pipe(gulp.dest(skinFolder));
});
return stream;
});
You cannot put a glob into gulp.dest as you are trying in your question.

convert gulp.src stream to array?

Is it possible to get the list of files coming from a gulp.src stream as an array, e.g.:
var files = convertToArray(gulp.src('**/*.js'));
Update:
I was trying to move away from the gulp-karma plugin:
gulp.task('test', function () {
return gulp.src(files)
.pipe($.order(ordering))
.pipe($.karma({
karma.conf.js'
});
});
So my idea was:
gulp.task('test', function (done) {
var karmaFiles = convertToArray(gulp.src(files)
.pipe($.order(ordering)));
new Server({
configFile: karma.conf.js',
files: karmaFiles
}, done).start();
});
But as pointed out, this won't work because of it being async. Here's my solution:
gulp.task('test', function (done) {
gulp.src(files)
.pipe($.order(ordering)))
.pipe(gutil.buffer())
.on('data', function(data) {
var karmaFiles = data.map(function(f) { return f.path; });
new Server({
configFile: __dirname + '/karma.conf.js',
files: karmaFiles
}, done).start();
});
});
Gulp streams are always asynchronous so your hypothetical convertToArray function (which takes a stream and returns an array) is impossible.
The only way to get all the files in a stream is through some kind of callback function. The gulp-util package, which bundles various helper functions, provides the nice gutil.buffer() :
var gutil = require('gulp-util');
gulp.src('**/*.js').pipe(gutil.buffer(function(err, files) {
console.log('Path of first file:');
console.log(files[0].path);
console.log('Contents of first file:');
console.log(files[0].contents.toString());
}));
In the above files will be an array of vinyl files. That means for each file you have access to both the contents and the path of the file.
If you don't care about the file contents and only want the path of each file you shouldn't be using gulp.src() at all. You should be using glob instead (which is what gulp is using internally). It gives you a synchronous method that returns an array of matching file paths:
var glob = require('glob');
var files = glob.sync('**/*.js');
console.log(files);

concatenating scss file with lots of other scss files

I have the next files structure:
modules/
list/
news/
news.scss
login/
login.scss
common/
common.scss
And I want to get next structure using gulp:
modules/
list/
news/
news.scss
news.css
login/
login.scss
login.css
common/
common.scss
Here is part from my gulpfile:
gulp.src("modules/list/*/*.scss")
.pipe(sass())
.pipe(gulp.dest("modules/list/"));
In common.scss there are different variables. It is necessary that variables from common.scss will be used in each module(news.scss, login.scss). How to update my gulpfile that common.scss will be concatenated with each module scss file?
Sounds like a job for stream arrays... here's the solution, please check the comments for what's going on:
var merge = require('merge2');
var glob = require('glob');
var gulp = require('gulp');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
gulp.task('styles', function(done) {
// first, we glob our files like we would with gulp.src
glob('modules/list/**/*.scss', function(er, files) {
// for each of those files we create a new stram
var tasks = files.map(function(file) {
// this gives us the concat name, which is the same
// as the original file's name
var concatStr = file.substr('modules/list/'.length)
// we load common.scss and our file
return gulp.src(['modules/common/common.scss', file])
// concatenate it
.pipe(concat(concatStr))
});
// we merge all our streams
merge(tasks)
// run them through sass
.pipe(sass())
// and save them where we want them
.pipe(gulp.dest('modules/list'));
// ~fin
done();
});
});
You might want to take a look into Sass's #import directive, though.