6

Is is possible using Gulp to copy a portion of HTML (not the entire file) and inject that into a different file?

I have found packages like https://www.npmjs.com/package/gulp-html-replace

and https://www.npmjs.com/package/gulp-inject-string

but they can't actually copy HTML.

CyberJunkie
  • 21,596
  • 59
  • 148
  • 215

3 Answers3

3

Handling HTML with regular expression is never advised, and there are many arguments (1, 2, 3) against that.

The most popular and reliable way to handle an HTML source is by constructing a document model of the source. JSDOM, is one node.js module that provides a good DOM construction API. Here's a demo of how to solve your case with JSDOM:

var fs = require("fs");
var gulp = require("gulp");

var dom = require("jsdom");
var domSerialiser = dom.serializeDocument;

var input = "input.html";
var output = "output.html";

gulp.task("copy-html", function () {
    var extractionPoint = "#extraction-location";
    var insertionPoint = "#insertion-location";

    extractFrom(input, extractionPoint).
            then(insertInto.bind(null, output, insertionPoint)).
            then(saveOutput);
});

function extractFrom(file, section) {
    return new Promise(function (resolve, reject) {
        dom.env({
            file: file,
            done: function (error, window) {
                var portion;

                if (error) {
                    reject(error);
                    return;
                }

                portion = window.document.querySelector(section);

                resolve(portion.outerHTML);
            }
        });
    });
}

function insertInto(file, section, portion) {
    return new Promise(function (resolve, reject) {
        dom.env({
            file: file,
            done: function (error, window) {
                if (error) {
                    reject(error);
                    return;
                }

                section = window.document.querySelector(section);
                // you may prefer to appendChild() instead, your call
                section.outerHTML = portion;

                resolve(domSerialiser(window.document));
            }
        });
    });
}

function saveOutput(data) {
    fs.writeFile(output, data, function (error) {
        if (error) {
            throw error;
        }

        console.log("Copied portion to output successfully.");
    });
}

I hope the example above provides a good basis for you to reach a solution specific to your issue.

Community
  • 1
  • 1
Igwe Kalu
  • 14,286
  • 2
  • 29
  • 39
2

you can do it using fs and replace, I don't know if it's the best way, but it's works for me.

  gulp.task('injectHtml', function() {
    return gulp.src('/dir/file_to_inject.html')
      .pipe(replace('<!-- injecthere -->', function() {
        var htmlContent = fs.readFileSync('/home/file_source.html', 'utf8');
        //regex to get the div content
        return htmlContent.match(/<div id="myDiv">(.*?)<\/div>/)[0];
      }))
      .pipe(gulp.dest('/dir'));
  });

file_source.html

<html>
 <div id="myDiv">test div</div>
</html>

file_to_inject.html

<html>
 <!-- injecthere -->
</html>
Rafael Zeffa
  • 2,334
  • 22
  • 20
  • Thanks for your solution. However, the regexp didnt work for me. This one did it: `/
    (.|\n)*?<\/div>/`. I need multiline content. Found it in [this answer](http://stackoverflow.com/questions/7167279/regex-select-all-text-between-tags#16880892)
    – mahish Jan 24 '17 at 11:48
2

Yes, I typically use through2 whenever I want to inject some custom code into the pipe:

var gulp = require('gulp');
var through2 = require('through2');
var fs = require('fs');

gulp.task('default', function(){
  gulp.src('./recipient.html')
    .pipe(through2.obj(function(file, enc, done){
      fs.readFile('./donor.html', function(err, data){
        if(err) throw "Something went horribly wrong.";
        // extract from data the HTML you want to insert
        var contents = file.contents.toString('utf8');
        // insert HTML into `contents`
        file.contents = new Buffer(contents);
        this.push(file)
        done();
      });
    });
});

This will pipe the recipient html file through gulp, then, read in the donor html file contents. From there you can manipulate both to your heart's content. Then you simply take the result, put it back into the file object, and push that sucker back into the gulp pipeline.

Trevor
  • 13,085
  • 13
  • 76
  • 99