edt
edt

Reputation: 22440

In a Gulp task, how can I set a variable value in the first pipe and read it in the second pipe?

I have a task with two piped statements. The second pipe relies on a global variable whose value is declared in the first pipe. But, I am not able to access the global variable from the second pipe. It seems like pipe 2 is starting before pipe 1 finishes.

var responsive = require('gulp-responsive');
var tap = require('gulp-tap');

// global variables for image-generator task
var imageA1Width = 0;
var imageA1Height = 0;

// extracts width and height from image path
function getDimensionsFromPath(path) {
    // example image: banner-fooBar-$a1-1000x901.jpg
    var path = path || '';
    var dimensionsString = '';
    var width = 0;
    var height = 0;
    var re = /[^-]*$/;
    dimensionsString = path.match(re)[0];
    dimensionsString = dimensionsString.replace('.jpg', '');
    dimensionsString = dimensionsString.replace('.png', '');
    dimensionsString = dimensionsString.replace('.webp', '');
    dimensionsString = dimensionsString.replace('.gif', '');
    var dimensionsArr = dimensionsString.split('x');
    width = parseInt(dimensionsArr[0], 10);
    height = parseInt(dimensionsArr[1], 10);
    var obj = {
        width: width,
        height: height
    };
    return obj;
}

gulp.task('image-generator', function () {
    var imageKeyPattern = /-\$a1.*$/; // example image: banner-fooBar-$a1-1000x901.jpg
    return gulp.src('images/**/*$a1*.*')
        .pipe(tap(function (file, t) {
            var imageA1Path = file.path;
            // global variables
            imageA1Width = getDimensionsFromPath(imageA1Path).width;
            imageA1Height = getDimensionsFromPath(imageA1Path).height;
        }))
        .pipe(responsive({
            '**/*$a1*.*': [{
                width: imageA1Width * 2, // NaN
                skipOnEnlargement: true,
                rename: function (opt) {
                    opt.basename = opt.basename.replace(imageKeyPattern, '-extralarge@2x');
                    opt.dirname = '';
                    return opt;
                }
            },
            ]
        }))
        .pipe(gulp.dest('imagesGenerated/'));
});

Upvotes: 1

Views: 2125

Answers (1)

Sven Schoenung
Sven Schoenung

Reputation: 30574

Problem:

You compute the value for the imageA1Width var in the tap() pipeline stage meaning the var is reset for every file moving through the stream.

However imageA1Width is evaluated only once (as part of the object literal that gets passed to responsive()) and before the stream has even been created. At that time imageA1Width is still undefined.

Solution:

What we need to do is compute a different width value for each file in the stream. Then for each file we need to call responsive() individually since each file will have a different width. We can do this using gulp-foreach:

var foreach = require('gulp-foreach');

gulp.task('image-generator', function () {
  var imageKeyPattern = /-\$a1.*$/;
  return gulp.src('images/**/*$a1*.*')
    .pipe(foreach(function(stream, file) {
       var size = getDimensionsFromPath(file.path);
       return stream
        .pipe(responsive({
           '**/*$a1*.*': [{
             width: size.width * 2,
             skipOnEnlargement: true,
             rename: function (opt) {
               opt.basename = opt.basename.replace(imageKeyPattern, 
                                                   '-extralarge@2x');
               opt.dirname = '';
               return opt;
             }
           }]
         }));
    }))
    .pipe(gulp.dest('imagesGenerated/'));
});

Upvotes: 1

Related Questions