How to push a gulp pipeline onto another - gulp

I would like to process a series of folders through the build pipeline. For each folder I start another gulp pipeline that will create some source files. Finally I'd like to pipe them all together through the zip() plugin to produce a final artifact.
The following pseudocode shows my approach. However, I cannot push the result of the gulp.src to the current pipeline.
return gulp.src(someFolder)
.pipe(through(function(folder, enc, cb){
// how to add the result of the following line to my
// own pipeline????
this.push(gulp.src(path.join(folder, "whatever"))
.pipe(somePlugin()));
}))
.pipe(zip(....))
.pipe(gulp.dest(....));
Any hints how to combine those pipelines together?

This is exactly what gulp-foreach is intended for. Using that the equivalent of the code you posted would look like this:
var foreach = require('gulp-foreach');
return gulp.src(someFolder)
.pipe(foreach(function(stream, folder) {
return gulp.src(path.join(folder.path, "whatever"))
.pipe(somePlugin());
}))
.pipe(zip(....))
.pipe(gulp.dest(....));
Note that the above will discard all files from the original gulp.src(someFolder). They will not be included in the ZIP. If you want to keep those around as well you can use merge-stream:
var foreach = require('gulp-foreach');
var merge = require('merge-stream');
return gulp.src(someFolder)
.pipe(foreach(function(stream, folder) {
return merge(stream,
gulp.src(path.join(folder.path, "whatever"))
.pipe(somePlugin()));
}))
.pipe(zip(....))
.pipe(gulp.dest(....));

Related

Glob watch multiple files, process one

I use Gulp 4 with gulp-sass. What I try to do is the following.
The code I provide here is just a fragment of the whole code, to show the important parts.
The watch should like it does, watch all .scss files.
In style(), only the current file is going to be processed.
If I save custom/components/header/header.scss, then only custom/components/header/header.scss should be processed, not all files.
The saved file should then have a filename like assets/css/dist/header/header.css
Both src and dest is unknown in this case because I don't have a single file to grab on to.
I see now that I also need to remove custom/components from the dest, but the important thing is that I can get the current file to start working with that.
gulp.watch('custom/components/**/*.scss', style);
function style() {
return gulp
.src()
.pipe(sass())
.on('error', sass.logError)
.pipe(gulp.dest('assets/css/dist'));
}
I just figure it out. It's possible to do it like this.
let watcher = gulp.watch(css.watch);
watcher.on('change', function(path) {
console.log(path);
style();
}

How to zip multiple folders generating multiple .zip files in gulp?

My folder structure looks like this:
- /projects
- /projects/proj1
- /projects/proj2
- /projects/proj3
- /zips
For each folder in projects (proj1, proj2 and proj3) I want to zip contents of each of those folders and generate proj1.zip, proj2.zip and proj3.zip in /zips folder.
Following example function generates single zip file from proj1 folder
zip = require('gulp-zip');
gulp.task('default', function () {
return gulp.src('./projects/proj1/*')
.pipe(zip('proj1.zip'))
.pipe(gulp.dest('./zips'));
});
But how I can execute such task for each folder in projects? I can get all folders to zip by gulp.src('./projects/*') but what then?
Old question I know and I am pretty new to gulp so this might be considered a hack but I have just been trying to do what you are after and I ended up with this.
My file structure is this:
proj
proj/dist
proj/dist/sub01
proj/dist/sub02
proj/dist/sub03
proj/zipped
And my task ended up like this:
var gulp = require("gulp");
var foreach = require("gulp-foreach");
var zip = require("gulp-zip");
gulp.task("zip-dist", function(){
return gulp.src("./dist/*")
.pipe(foreach(function(stream, file){
var fileName = file.path.substr(file.path.lastIndexOf("/")+1);
gulp.src("./dist/"+fileName+"/**/*")
.pipe(zip(fileName+".zip"))
.pipe(gulp.dest("./zipped"));
return stream;
}));
});
It grabs all the first level contents of ./dist as its source and then pipes it to gulp-foreach.
gulp-foreach looks at each item and I use a plain javascript substr() to get the name of the current item which I store as a variable.
Finally I set a new src using the stored fileName var and pipe the result to gulp-zip using the stored var again as the name of the zipped file.
The result is a structure that looks like this:
proj
proj/dist
proj/dist/sub01
proj/dist/sub02
proj/dist/sub03
proj/zipped
proj/zipped/sub01.zip
proj/zipped/sub02.zip
proj/zipped/sub03.zip
Again, I am a million miles from being an expert but this worked for me and if I understand the question might work for you as well or at least give you some ideas.

how to modify config files using gulp

I use gulp to configure complex local setup and need to auto-edit files.
The scenario is:
determine if certain file contains certain lines after certain other line (found using regular expression)
if line is not found, insert the line.
optionally, delete some lines found in the file.
I need this to amend system configuration files and compile scenarios.
What would be the best way to do it in gulp?
Gulp is plain javascript. So what I would do if I were you is to create a plugin to pipe to the original config file.
Gulp streams emit Vinyl files. So all you really got to do is to create a "pipe factory" that transforms the objects.
It would look something like this (using EventStream):
var es = require('event-stream');
// you could receive params in here if you're using the same
// plugin in different occasions.
function fixConfigFile() {
return es.map(function(file, cb) {
var fileContent = file.contents.toString();
// determine if certain file contains certain lines...
// if line is not found, insert the line.
// optionally, delete some lines found in the file.
// update the vinyl file
file.contents = new Buffer(fileContent);
// send the updated file down the pipe
cb(null, file);
});
}
gulp.task('fix-config', function() {
return gulp.src('path/to/original/*.config')
.pipe(fixConfigFile())
.pipe(gulp.dest('path/to/fixed/configs');
});
Or you can use vinyl-map:
const map = require('vinyl-map')
const gulp = require('gulp')
const modify = map((contents, filename) => {
contents = contents.toString()
// modify contents somehow
return contents
})
gulp.task('modify', () =>
gulp.src(['./index.js'])
.pipe(modify)
.pipe(gulp.dest('./dist'))
})

How to zip up zip files using Gulp Zip

I've started using Gulp JS and must admit I'm finding it really useful.
One of the tasks I need to perform is zip up a collection of folders into individual zip files, one for each folder and then zip all this zipped files up into one single zip file. Using Gulp-Zip I've managed to get this far:
var modelFolders = [
'ELFH_Check',
'ELFH_DDP',
'ELFH_Free'
];
gulp.task('zipModels', function () {
for (var i = 0; i < modelFolders.length; i++) {
var model = modelFolders[i];
gulp.src('**/*', {cwd: path.join(process.cwd(), '/built_templates/' + model) })
.pipe(zip(model + '.zip'))
.pipe(gulp.dest('./built_templates'));
};
});
This works and outputs ELFH_Check.zip, ELFH_DDP.zip and ELFH_Free.zip. However, I then need to zip up these zip files into one zip file called "Templates.zip" and I've not managed to get this task to work:
// zip up model files
gulp.task('zipTemplate', ['zipModels'], function () {
gulp.src('*.zip', {cwd: path.join(process.cwd(), './built_templates/') })
.pipe(zip('Templates_.zip'))
.pipe(gulp.dest('./built_templates'));
});
Does anyone know if this is possible or what I'm doing wrong?
I saw the problem as well, and it seems to be related to the cwd option somehow. I'll investigate further.
After #OverZealous comment, I investigated further and found two issues:
As he said, you need to hint gulp to wait until the end of the dependency task (zipModels), by returning a stream from it. As you have multiple streams, you can use event-stream.merge to return a bundle stream.
The reason why the bundle zip wouldn't work, is because you cwd points to /built_templates/, and the second slash is causing some problem. To work properly, you need to remove the trailing slash, so it should be path.join(process.cwd(), '/built_templates').
IMPORTANT
Anyway, you should avoid temporary files. Gulp philosophy is to try using pipes to avoid IO. In that direction, what you want to do is to cut the intermediary dest steps, merge the streams, zip them, and finally, output them.
Something like that:
var es = require('event-stream');
var modelFolders = [
'ELFH_Check',
'ELFH_DDP',
'ELFH_Free'
];
gulp.task('zipModels', function () {
var zips = [],
modelZip;
for (var i = 0; i < modelFolders.length; i++) {
var model = modelFolders[i];
modelZip = gulp.src('**/*', {cwd: path.join(process.cwd(), '/built_templates/' + model) })
.pipe(zip(model + '.zip'));
// notice we removed the dest step and store the zip stream (still in memory)
zips.push(modelZip);
};
// we finally merge them (the zips), zip them again, and output.
return es.merge.apply(null, zips)
.pipe(zip('templates.zip'))
.pipe(gulp.dest('./'));
});
By the name of your folder (built_templates), it seems you have some other task that will generate the temporary built files. Preferably, you don't want these as well. You should pipe their streams directly to the ZIP stream, a finally, to the bundle-zip stream. By doing that, you would have a simple stream flow, with one disk read, and one disc write at the end, with no temporary files.
If you need them to be different tasks, consider having a function that will generate the stream up to the step before the gulp.dest pipe, and use this function on all subtasks.
Additionally, always try to hint your async tasks by returning a stream, a promise or receiving a callback function, and advise the end of the task.

Get the current file name in gulp.src()

In my gulp.js file I'm streaming all HTML files from the examples folder into the build folder.
To create the gulp task is not difficult:
var gulp = require('gulp');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(gulp.dest('./build'));
});
But I can't figure out how retrieve the file names found (and processed) in the task, or I can't find the right plugin.
I'm not sure how you want to use the file names, but one of these should help:
If you just want to see the names, you can use something like gulp-debug, which lists the details of the vinyl file. Insert this anywhere you want a list, like so:
var gulp = require('gulp'),
debug = require('gulp-debug');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(debug())
.pipe(gulp.dest('./build'));
});
Another option is gulp-filelog, which I haven't used, but sounds similar (it might be a bit cleaner).
Another options is gulp-filesize, which outputs both the file and it's size.
If you want more control, you can use something like gulp-tap, which lets you provide your own function and look at the files in the pipe.
I found this plugin to be doing what I was expecting: gulp-using
Simple usage example: Search all files in project with .jsx extension
gulp.task('reactify', function(){
gulp.src(['../**/*.jsx'])
.pipe(using({}));
....
});
Output:
[gulp] Using gulpfile /app/build/gulpfile.js
[gulp] Starting 'reactify'...
[gulp] Finished 'reactify' after 2.92 ms
[gulp] Using file /app/staging/web/content/view/logon.jsx
[gulp] Using file /app/staging/web/content/view/components/rauth.jsx
Here is another simple way.
var es, log, logFile;
es = require('event-stream');
log = require('gulp-util').log;
logFile = function(es) {
return es.map(function(file, cb) {
log(file.path);
return cb(null, file);
});
};
gulp.task("do", function() {
return gulp.src('./examples/*.html')
.pipe(logFile(es))
.pipe(gulp.dest('./build'));
});
You can use the gulp-filenames module to get the array of paths.
You can even group them by namespaces:
var filenames = require("gulp-filenames");
gulp.src("./src/*.coffee")
.pipe(filenames("coffeescript"))
.pipe(gulp.dest("./dist"));
gulp.src("./src/*.js")
.pipe(filenames("javascript"))
.pipe(gulp.dest("./dist"));
filenames.get("coffeescript") // ["a.coffee","b.coffee"]
// Do Something With it
For my case gulp-ignore was perfect.
As option you may pass a function there:
function condition(file) {
// do whatever with file.path
// return boolean true if needed to exclude file
}
And the task would look like this:
var gulpIgnore = require('gulp-ignore');
gulp.task('task', function() {
gulp.src('./**/*.js')
.pipe(gulpIgnore.exclude(condition))
.pipe(gulp.dest('./dist/'));
});
If you want to use #OverZealous' answer (https://stackoverflow.com/a/21806974/1019307) in Typescript, you need to import instead of require:
import * as debug from 'gulp-debug';
...
return gulp.src('./examples/*.html')
.pipe(debug({title: 'example src:'}))
.pipe(gulp.dest('./build'));
(I also added a title).