jsbin/public/js/runner/processor.js

108 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/** =========================================================================
* Processor
* Modify the prepared source ready to be written to an iframe
* ========================================================================== */
var processor = (function () {
var processor = {};
processor.blockingMethods = {
kill: '<script>try{window.open=function(){};window.print=function(){};window.alert=function(){};window.prompt=function(){};window.confirm=function(){};}catch(e){}</script>',
// RS: the empty comment in the end of the harness, ensures any
// open comments are closed, and will ensure the harness is hidden
// from the user.
restore: '<!--jsbin live harness--><script>try{delete window.print;delete window.alert;delete window.prompt;delete window.confirm;delete window.open;}catch(e){}</script>'
};
/**
* Grab the doctype from a string.
*
* Returns an object with doctype and tail keys.
*/
processor.getDoctype = (function () {
// Cached regex
// [\s\S] matches multiline doctypes
var regex = /<!doctype [\s\S]*?>/i;
return function (str) {
var doctype = (str.match(regex) || [''])[0],
tail = str.substr(doctype.length);
return {
doctype: doctype,
tail: tail
};
};
}());
/**
* Replace HTML characters with encoded equivatents for debug mode.
*/
processor.debug = function (source) {
return '<pre>' + source.replace(/[<>&]/g, function (m) {
if (m == '<') return '&lt;';
if (m == '>') return '&gt;';
if (m == '&') return '&amp;';
}) + '</pre>';
};
/**
* Render build the final source code to be written to the iframe. Takes
* the original source and an options object.
*/
processor.render = function (source, options) {
options = options || [];
source = source || '';
var combinedSource = [],
realtime = (options.requested !== true),
noRealtimeJs = (options.includeJsInRealtime === false);
// If the render was realtime and we don't want javascript in realtime
// renders Auto-run JS is unchecked then strip out the Javascript
if (realtime && noRealtimeJs) {
source = source.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}
// Strip autofocus from the markup, preventing the focus switching out of
// the editable area.
source = source.replace(/(<.*?\s)(autofocus)/g, '$1');
// Make sure the doctype is the first thing in the source
var doctypeObj = processor.getDoctype(source),
doctype = doctypeObj.doctype;
source = doctypeObj.tail;
combinedSource.push(doctype);
// Kill the blocking functions
// IE requires that this is done in the script, rather than off the window
// object outside of the doc.write.
if (realtime && options.includeJsInRealtime) {
combinedSource.push(processor.blockingMethods.kill);
}
// Push the source, split from the doctype above.
combinedSource.push(source);
// Restore the blocking functions
if (realtime && options.includeJsInRealtime) {
combinedSource.push(processor.blockingMethods.restore);
}
// In debug mode return an escaped version
if (options.debug) {
return processor.debug(combinedSource.join('\n'));
}
return combinedSource.join('\n');
};
return processor;
}());
if (typeof exports !== 'undefined') {
module.exports = processor;
}