From 78a3ec56506cdcfe30588a303b07d5f104562cf6 Mon Sep 17 00:00:00 2001 From: Nitin Hayaran Date: Fri, 28 Feb 2014 15:33:33 +0530 Subject: [PATCH] replaceRequireScript fix for conditional html in head and for django template tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If html have some conditional html or template tags in start of the file, they get messed up because of template parsing. Presently we don’t parse the html, we use regex to find script tag and then replace it. --- lib/replace.js | 56 ++++++++++--------- package.json | 5 +- test/fixtures/replaceConditionalComments.html | 16 ++++++ test/fixtures/replaceInDjangoTemplates.html | 17 ++++++ test/require_test.js | 42 ++++++++++++++ 5 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 test/fixtures/replaceConditionalComments.html create mode 100644 test/fixtures/replaceInDjangoTemplates.html diff --git a/lib/replace.js b/lib/replace.js index d5633b1..22ac3e9 100644 --- a/lib/replace.js +++ b/lib/replace.js @@ -11,9 +11,7 @@ exports.init = function(grunt) { // External libs. var Q = require('q'); - var jsdom = require('jsdom'); - var fs = require('fs'); - var rBody = //; + var cheerio = require('cheerio'); return function(config) { var deferred = Q.defer(); @@ -29,36 +27,40 @@ exports.init = function(grunt) { var filesEvaluated = 0; // iterate over found html files - files.forEach(function(file) { - var fileContents = fs.readFileSync(file, 'utf-8'); - var hasBody = rBody.test(fileContents); + files.forEach(function (file) { + // load file contents + var contents = String(grunt.file.read(file, 'utf-8')); + // reference to script regex https://github.com/jquery/jquery/blob/1.7.2/src/ajax.js#L14 + var script_re = /)<[^<]*)*<\/script>/gi, + matches = contents.match(script_re); - jsdom.env(fileContents, { - FetchExternalResources: false, - ProcessExternalResources: false - }, function(err, window) { - var scripts = window.document.querySelectorAll('script[data-main]'); - - [].slice.call(scripts).forEach(function(script) { - var insertScript = (file.modulePath || script.getAttribute('data-main')); - script.src = insertScript + '.js'; - script.removeAttribute('data-main'); - }); - - var html = hasBody ? window.document.innerHTML : window.document.body.innerHTML; - grunt.log.writeln('Updating requirejs script tag for file', file); - grunt.file.write(file, html); - - // only resolve after all files have been evaluated - filesEvaluated++; - if (filesEvaluated >= files.length) { - deferred.resolve(config); + [].slice.call(matches).forEach(function(match, i){ + var $ = cheerio.load(match), + elm = $('script'); + if (elm.attr('data-main')){ + var insertScript = (file.modulePath || elm.attr('data-main')); + elm.attr('src', insertScript + '.js'); + elm.removeAttr('data-main'); + // replace i'th occurrence in content + var j = 0; + contents = contents.replace(script_re, function(match){ + j++; + return (j-1 === i) ? $.html() : match; + }); } }); + + grunt.log.writeln('Updating requirejs script tag for file', file); + grunt.file.write(file, contents); + // only resolve after all files have been evaluated + filesEvaluated++; + if (filesEvaluated >= files.length) { + deferred.resolve(config); + } + }); }); return deferred.promise; }; }; - diff --git a/package.json b/package.json index af8657b..433af22 100644 --- a/package.json +++ b/package.json @@ -29,11 +29,10 @@ }, "dependencies": { "requirejs": "2.1.x", - "cheerio": "0.10.x", + "cheerio": "0.13.x", "almond": "0.2.x", "gzip-js": "0.3.x", - "q": "0.8.x", - "jsdom": "0.8.x" + "q": "0.8.x" }, "devDependencies": { "grunt": "~0.4.0", diff --git a/test/fixtures/replaceConditionalComments.html b/test/fixtures/replaceConditionalComments.html new file mode 100644 index 0000000..0f5cd19 --- /dev/null +++ b/test/fixtures/replaceConditionalComments.html @@ -0,0 +1,16 @@ + + + + + + + + Testing + + + + + + + + diff --git a/test/fixtures/replaceInDjangoTemplates.html b/test/fixtures/replaceInDjangoTemplates.html new file mode 100644 index 0000000..d1c12ff --- /dev/null +++ b/test/fixtures/replaceInDjangoTemplates.html @@ -0,0 +1,17 @@ +{% load static %} + + + + + + + + Testing + + + + + + + + diff --git a/test/require_test.js b/test/require_test.js index 5bc56d1..cbab57e 100644 --- a/test/require_test.js +++ b/test/require_test.js @@ -302,6 +302,48 @@ exports['require'] = { result = grunt.file.read('node_modules/almond/almond.js'); test.ok(result.length > 0, 'original almond.js should still be there'); test.done(); + }, + + 'requirejs script tag should be replaced without messing with conditional html': function(test) { + 'use strict'; + test.expect(2); + var config = { + replaceRequireScript: [{ + files: ['tmp/replaceConditionalComments.html'], + module: 'main' + }], + modules: [{name: 'main'}], + almond: true + }; + + grunt.file.copy('test/fixtures/replaceConditionalComments.html', 'tmp/replaceConditionalComments.html'); + replaceAlmondInHtmlFiles(config).then(function() { + var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]); + test.ok(replacedFileContents.search('') > -1, 'should replace script tag ´src´ contents'); + test.ok(replacedFileContents.search('