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

stripScripts now loads & executes external files #2691

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion Docs/Types/String.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,12 @@ Strips the String of its *<script>* tags and anything in between them.

### Arguments:

1. evaluate - (*boolean*, optional) If true is passed, the scripts within the String will be evaluated.
1. evaluate - (*boolean* or *function*, optional) If true is passed, the scripts within the String will be evaluated. All external scripts are loaded synchronously & executed. If "evaluate" is a function, it is called back with the following arguments:

* (*string*) - JavaScript Code between <script> and </script> tags.
* (*string*) - The stripped text.
* (*array*) - Array of urls of external JavaScript files (if any).
* (*function*) - Callback function that executes all stripped JavaScript (inline + external) synchronously.

### Returns:

Expand All @@ -396,6 +401,18 @@ Strips the String of its *<script>* tags and anything in between them.
var myString = "<script>alert('Hello')</script>Hello, World.";
myString.stripScripts(); // returns 'Hello, World.'
myString.stripScripts(true); // alerts 'Hello', then returns 'Hello, World.'

var html = '<div id="placeholder"></div>' +
'<script src="https://rawgithub.com/mootools/mootools-more/master/Source/More/More.js"></script>' +
'<script>document.id("placeholder").set("text", "Hello, world")</script>';
html.stripScripts(function(code, html, urls, exec){
// inject the stripped HTML
document.body.innerHTML = html;
// execute all JavaScript
exec(function(){
alert('All scripts loaded and executed!');
});
});



Expand Down
37 changes: 32 additions & 5 deletions Source/Browser/Browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,40 @@ Browser.exec = function(text){
};

String.implement('stripScripts', function(exec){
var scripts = '';
var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
scripts += code + '\n';
var scripts = [];
var inline = '';

var text = this.replace(/<script[^>]*?(?:src=(?:"|')?([^"]+)(?:"|')?[^>]*)?>([\s\S]*?)<\/script>/gi, function( all, src, code ) {
inline += code + '\n';
scripts.push({
type: src ? 'src' : 'code',
source: src || code
});
return '';
});
if (exec === true) Browser.exec(scripts);
else if (typeOf(exec) == 'function') exec(scripts, text);

var urls = scripts.map(function(el){ return el.type == 'src' ? el.source : undefined; }).clean();
var next = function(callback){
if (!scripts.length){
typeof callback == 'function' && callback();
return;
}
var script = scripts.shift();
if (script.type == 'code'){
Browser.exec(script.source);
next(callback);
} else {
new Element('script', {
src: script.source,
events: {
load: function(){ next(callback); }
}
}).inject(document.head);
}
}

if (exec === true) next();
else if (typeof exec == 'function') exec(inline, text, urls, next);
return text;
});

Expand Down
24 changes: 23 additions & 1 deletion Specs/Browser/Browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,33 @@ describe('String.stripScripts', function(){
it('should execute the stripped tags from the string', function(){
expect('<div><script type="text/javascript"> var stripScriptsSpec = 42; </script></div>'.stripScripts(true)).toEqual('<div></div>');
expect(window.stripScriptsSpec).toEqual(42);
expect('<div><script>\n// <!--\nvar stripScriptsSpec = 24;\n//-->\n</script></div>'.stripScripts(true)).toEqual('<div></div>');
expect('<div><script id="my-script">\n// <!--\nvar stripScriptsSpec = 24;\n//-->\n</script></div>'.stripScripts(true)).toEqual('<div></div>');
expect(window.stripScriptsSpec).toEqual(24);
expect('<div><script>\n/*<![CDATA[*/\nvar stripScriptsSpec = 4242;\n/*]]>*/</script></div>'.stripScripts(true)).toEqual('<div></div>');
expect(window.stripScriptsSpec).toEqual(4242);
});

it('should load & execute script files synchronously', function(){
var div = new Element('div').inject(document.body);
[
'<div id="my-container"></div>',
'<script>',
'document.id("my-container").set("text", "dynamic content");',
'</script>',
'<script id="mt-more-More">',
'Drag = undefined;',
'</script>',
'<script type="text/javascript" id="mt-more-Drag" src="https://rawgithub.com/mootools/mootools-more/master/Source/Drag/Drag.js"></script>',
'<script src="https://rawgithub.com/mootools/mootools-more/master/Source/Drag/Drag.Move.js" id="mt-more-Drag-Move" type="text/javascript"></script>',
'<script>',
'new Drag.Move(div);',
'</script>'
].join('').stripScripts(function(code, html, urls, fn){
div.set('html', html);
fn();
expect(div.get('text')).toEqual('dynamic content');
});
});

});

Expand Down