Use gulp to copy the contents of one glob file into a line of another glob file

415 Views Asked by At

I'm working on a web component build process that takes the contents of a HTML file and puts them into a string in my javascript file.

I want to get the contents of /src/foo/bar.html and add them to /dist/foo/bar.js

At the moment, I'm using gulp-tap and fs to read in the html which works, and I'm using gulp-string-replace to add the string to my js file, as follows:

const gulp = require('gulp');
const fs = require('fs');
const replace = require('gulp-string-replace');
const tap = require('gulp-tap');

gulp.task('add-html', function () {
    // Use these variables for Gulp-string-replace
    const startHTML = "<!-- Start html -->";
    const endHTML = "<!-- End html -->";
    const regEx = new RegExp(
        startHTML + "[\\s\\S]*" + endHTML,
        "i"
    );
    let htmlInjection;
    return gulp.src(['dist/**/*.js'])
        .pipe(tap(function (file, t) {
            // get to html file
            const htmlFile =
                file.path
                    .replace(/\.js$/i, ".html")
                    .replace(/dist/, "src");

            // read html, clean it up and add it to htmlInjection
            fs.readFile(htmlFile, function (err, data) {
                if (!err && data) {
                    const cleanHTMLString =
                        data.toString()
                            .split('\n')
                            .join('')
                            .replace(/\s+/g, ' ')
                            .trim();
                    htmlInjection =
                        startHTML +
                        cleanHTMLString +
                        endHTML;
                }
            });
        }))
        .pipe(replace(regEx, htmlInjection)) // Replace <!-- Start html --> foo <!-- End html --> with <!-- Start html --> <bar></bar> <!-- End html -->
        .pipe(gulp.dest('dist'));
});

This isn't working yet, as htmlInjection is undefined when replace happens. I believe this is due to the pipes being async.

I was referencing this Question Passing a variable between pipes in Gulp 3.9.1 and was wondering if this approach is even the best approach possible?

Are there any easier ways to achieve what I'm trying to here?

Thanks!

1

There are 1 best solutions below

0
On

I found a solution that lowers complexity relatively well.

By using gulp-replace instead of gulp-string-replace, you can get the file path inside your replace function like so:

var replace = require('gulp-replace');
 
gulp.task('templates', function(){
  gulp.src(['file.txt'])
    .pipe(replace('filename', function() {
      // Replaces instances of "filename" with "file.txt"
      // this.file is also available for regex replace
      // See https://github.com/gulpjs/vinyl#instance-properties for details on available properties
      return this.file.relative;
    }))
    .pipe(gulp.dest('build/'));
}); 

So instead of having two pipes, one for gulp-tap and one for gulp-string-replace, I just have the one gulp-replace pipe. My code now looks like this:

const gulp = require('gulp');
const fs = require('fs');
const replace = require("gulp-replace");

gulp.task('compileHTML', function () {
    const startHTML = "<!-- Start html -->";
    const endHTML = "<!-- End html -->";
    //Creates the regEx this ways so I can pass the variables.
    const regEx = new RegExp(startHTML + "[\\s\\S]*" + endHTML,"i");
    return gulp.src('dist/**/*.js')
        .pipe(replace(regEx, function () {
            let htmlFile = this.file.path.replace(/\.js$/i, ".html").replace(/dist/, "src");

            const html = fs.readFileSync(htmlFile);
            const cleanHTMLString =
                // cleaning logic
            injectHTMLContent = startHTML + cleanHTMLString + endHTML;
            return injectHTMLContent;
        }))
        .pipe(gulp.dest('dist'));
});

It's not the cleanest implementation, but hopefully this will help others in the future.