Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replaceRequireScript fix for conditional html in head and for templates #90

Merged
merged 1 commit into from
Mar 2, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 29 additions & 27 deletions lib/replace.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ exports.init = function(grunt) {

// External libs.
var Q = require('q');
var jsdom = require('jsdom');
var fs = require('fs');
var rBody = /<body>/;
var cheerio = require('cheerio');

return function(config) {
var deferred = Q.defer();
Expand All @@ -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\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/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;
};
};

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 16 additions & 0 deletions test/fixtures/replaceConditionalComments.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Testing</title>
<!-- build:js scripts/vendor/modernizr.js -->
<script src="bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
</head>
<body>
<script src="js/require.js" data-main="js/main"></script>
</body>
</html>
17 changes: 17 additions & 0 deletions test/fixtures/replaceInDjangoTemplates.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% load static %}
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Testing</title>
<!-- build:js scripts/vendor/modernizr.js -->
<script src="bower_components/modernizr/modernizr.js"></script>
<!-- endbuild -->
</head>
<body>
<script src="js/require.js" data-main="js/main"></script>
</body>
</html>
42 changes: 42 additions & 0 deletions test/require_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('<script src="js/main.js"></script>') > -1, 'should replace script tag ´src´ contents');
test.ok(replacedFileContents.search('<!--\\[if lt IE 7\\]>') > -1, 'should not mess with conditional html');
test.done();
});
},

'requirejs script tag should be replaced without altering django template tags': function(test) {
'use strict';
test.expect(2);
var config = {
replaceRequireScript: [{
files: ['tmp/replaceInDjangoTemplates.html'],
module: 'main'
}],
modules: [{name: 'main'}],
almond: true
};

grunt.file.copy('test/fixtures/replaceInDjangoTemplates.html', 'tmp/replaceInDjangoTemplates.html');
replaceAlmondInHtmlFiles(config).then(function() {
var replacedFileContents = grunt.file.read(config.replaceRequireScript[0].files[0]);
test.ok(replacedFileContents.search('<script src="js/main.js"></script>') > -1, 'should replace script tag ´src´ contents');
test.ok(replacedFileContents.search('{% load static %}') > -1, 'should not mess with conditional html');
test.done();
});
}

};