summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McLear <john@mclear.co.uk>2012-02-26 14:49:13 +0000
committerJohn McLear <john@mclear.co.uk>2012-02-26 14:49:13 +0000
commitaa78456ab93e8e1eaffb240147ce6cbe7715a000 (patch)
treeb5f0fe645c244ff2fbee0728a3983f5fa94ad0ff
parent8d764cad33b7f8be7b5883b965c95d4dcbce6ffa (diff)
downloadetherpad-lite-aa78456ab93e8e1eaffb240147ce6cbe7715a000.zip
Revert "drop embedding of JS/CSS files in ace.js. May result in a little performance drop but makes code much smaller"
This reverts commit 9ede14a546731e692640a408c2b5bdb07d2c2c59.
-rw-r--r--node/utils/Minify.js74
-rw-r--r--static/js/ace.js160
2 files changed, 177 insertions, 57 deletions
diff --git a/node/utils/Minify.js b/node/utils/Minify.js
index baeaee68..859ee07a 100644
--- a/node/utils/Minify.js
+++ b/node/utils/Minify.js
@@ -213,6 +213,72 @@ function _handle(req, res, jsFilename, jsFiles) {
}
}
+// find all includes in ace.js and embed them.
+function getAceFile(callback) {
+ fs.readFile(JS_DIR + 'ace.js', "utf8", function(err, data) {
+ if(ERR(err, callback)) return;
+
+ // Find all includes in ace.js and embed them
+ var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\([a-zA-Z0-9.\/_"-]+\)/gi);
+ if (!settings.minify) {
+ founds = [];
+ }
+ founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');
+
+ data += ';\n';
+ data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';
+
+ //go trough all includes
+ async.forEach(founds, function (item, callback) {
+ var filename = item.match(/"([^"]*)"/)[1];
+ var type = item.match(/INCLUDE_([A-Z]+)/)[1];
+ var shortFilename = (filename.match(/^..\/static\/js\/(.*)$/, '')||[])[1];
+
+ //read the included files
+ if (shortFilename) {
+ if (shortFilename == 'require-kernel.js') {
+ // the kernel isn’t actually on the file system.
+ handleEmbed(null, requireDefinition());
+ } else {
+ var contents = '';
+ tarCode(tar[shortFilename] || shortFilename
+ , function (content) {
+ contents += content;
+ }
+ , function () {
+ handleEmbed(null, contents);
+ }
+ );
+ }
+ } else {
+ fs.readFile(ROOT_DIR + filename, "utf8", handleEmbed);
+ }
+
+ function handleEmbed(error, data_) {
+ if (error) {
+ return; // Don't bother to include it.
+ }
+ if (settings.minify) {
+ if (type == "JS") {
+ try {
+ data_ = compressJS([data_]);
+ } catch (e) {
+ // Ignore, include uncompresseed, which will break in browser.
+ }
+ } else {
+ data_ = compressCSS([data_]);
+ }
+ }
+ data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
+ + JSON.stringify(data_) + ';\n';
+ callback();
+ }
+ }, function(error) {
+ callback(error, data);
+ });
+ });
+}
+
exports.requireDefinition = requireDefinition;
function requireDefinition() {
return 'var require = ' + RequireKernel.kernelSource + ';\n';
@@ -222,8 +288,12 @@ function tarCode(jsFiles, write, callback) {
write('require.define({');
var initialEntry = true;
async.forEach(jsFiles, function (filename, callback){
- fs.readFile(JS_DIR + filename, "utf8", handleFile);
-
+ if (filename == 'ace.js') {
+ getAceFile(handleFile);
+ } else {
+ fs.readFile(JS_DIR + filename, "utf8", handleFile);
+ }
+
function handleFile(err, data) {
if(ERR(err, callback)) return;
var srcPath = JSON.stringify('/' + filename);
diff --git a/static/js/ace.js b/static/js/ace.js
index 63b1e61f..6c7bb84e 100644
--- a/static/js/ace.js
+++ b/static/js/ace.js
@@ -133,6 +133,74 @@ function Ace2Editor()
return info.ace_getUnhandledErrors();
};
+
+
+ function sortFilesByEmbeded(files) {
+ var embededFiles = [];
+ var remoteFiles = [];
+
+ if (Ace2Editor.EMBEDED) {
+ for (var i = 0, ii = files.length; i < ii; i++) {
+ var file = files[i];
+ if (Object.prototype.hasOwnProperty.call(Ace2Editor.EMBEDED, file)) {
+ embededFiles.push(file);
+ } else {
+ remoteFiles.push(file);
+ }
+ }
+ } else {
+ remoteFiles = files;
+ }
+
+ return {embeded: embededFiles, remote: remoteFiles};
+ }
+ function pushRequireScriptTo(buffer) {
+ var KERNEL_SOURCE = '../static/js/require-kernel.js';
+ var KERNEL_BOOT = 'require.setRootURI("../minified/");\nrequire.setGlobalKeyPath("require");'
+ if (Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
+ buffer.push('<script type="text/javascript">');
+ buffer.push(Ace2Editor.EMBEDED[KERNEL_SOURCE]);
+ buffer.push(KERNEL_BOOT);
+ buffer.push('<\/script>');
+ }
+ }
+ function pushScriptsTo(buffer) {
+ /* Folling is for packaging regular expression. */
+ /* $$INCLUDE_JS("../static/js/ace2_inner.js"); */
+ var ACE_SOURCE = '../static/js/ace2_inner.js';
+ if (Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[ACE_SOURCE]) {
+ buffer.push('<script type="text/javascript">');
+ buffer.push(Ace2Editor.EMBEDED[ACE_SOURCE]);
+ buffer.push('require("/ace2_inner");');
+ buffer.push('<\/script>');
+ } else {
+ file = ACE_SOURCE;
+ file = file.replace(/^\.\.\/static\/js\//, '../minified/');
+ buffer.push('<script type="application/javascript" src="' + file + '"><\/script>');
+ buffer.push('<script type="text/javascript">');
+ buffer.push('require("/ace2_inner");');
+ buffer.push('<\/script>');
+ }
+ }
+ function pushStyleTagsFor(buffer, files) {
+ var sorted = sortFilesByEmbeded(files);
+ var embededFiles = sorted.embeded;
+ var remoteFiles = sorted.remote;
+
+ if (embededFiles.length > 0) {
+ buffer.push('<style type="text/css">');
+ for (var i = 0, ii = embededFiles.length; i < ii; i++) {
+ var file = embededFiles[i];
+ buffer.push(Ace2Editor.EMBEDED[file].replace(/<\//g, '<\\/'));
+ }
+ buffer.push('<\/style>');
+ }
+ for (var i = 0, ii = remoteFiles.length; i < ii; i++) {
+ var file = remoteFiles[i];
+ buffer.push('<link rel="stylesheet" type="text/css" href="' + file + '"\/>');
+ }
+ }
+
editor.destroy = pendingInit(function()
{
info.ace_dispose();
@@ -140,9 +208,7 @@ function Ace2Editor()
delete ace2.registry[info.id];
info = null; // prevent IE 6 closure memory leaks
});
-
-
editor.init = function(containerId, initialCode, doneFunc)
{
@@ -154,8 +220,7 @@ function Ace2Editor()
doActionsPendingInit();
doneFunc();
};
-
- // This function builds the DOM structure of the editor which consists of two nested iFrames
+
(function()
{
var doctype = "<!doctype html>";
@@ -175,64 +240,50 @@ function Ace2Editor()
for (var i = 0, ii = iframeHTML.length; i < ii; i++) {
iframeHTML[i] = JSON.parse(iframeHTML[i]);
}
-
-
- // Build HTML of editable iFrame
-
- // Add Stylesheets to iFrame
- iframeHTML.push('<link rel="stylesheet" type="text/css" href="../static/css/iframe_editor.css">');
- iframeHTML.push('<link rel="stylesheet" type="text/css" href="../static/css/pad.css">');
- iframeHTML.push('<link rel="stylesheet" type="text/css" href="../static/custom/pad.css">');
-
- // Include Require Kernel and ace2_innner.js in iFrame;
- iframeHTML.push('<script type="text/javascript" src="../static/js/require-kernel.js"></script>');
- iframeHTML.push('<script type="text/javascript">');
-
- // Configure reqire
- iframeHTML.push('require.setRootURI("../minified/");');
- iframeHTML.push('require.setGlobalKeyPath("require");');
-
+
+ // calls to these functions ($$INCLUDE_...) are replaced when this file is processed
+ // and compressed, putting the compressed code from the named file directly into the
+ // source here.
+ // these lines must conform to a specific format because they are passed by the build script:
+ var includedCSS = [];
+ var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)};
+ $$INCLUDE_CSS("../static/css/iframe_editor.css");
+ $$INCLUDE_CSS("../static/css/pad.css");
+ $$INCLUDE_CSS("../static/custom/pad.css");
+ pushStyleTagsFor(iframeHTML, includedCSS);
+
+ var includedJS = [];
+ var $$INCLUDE_JS = function(filename) {includedJS.push(filename)};
+ pushRequireScriptTo(iframeHTML);
// Inject my plugins into my child.
- iframeHTML.push('require.define("/plugins", null);');
- iframeHTML.push('require.define("/plugins.js", function (require, exports, module) {');
- iframeHTML.push('module.exports = parent.parent.require("/plugins");');
- iframeHTML.push('});');
- iframeHTML.push('<\/script>');
-
- // Require ace2
- iframeHTML.push('<script type="text/javascript" src="../minified/ace2_inner.js"></script>');
- iframeHTML.push('<script type="text/javascript">');
- iframeHTML.push('require("/ace2_inner");');
- iframeHTML.push('<\/script>');
-
+ iframeHTML.push('\
+<script type="text/javascript">\
+ require.define("/plugins", null);\n\
+ require.define("/plugins.js", function (require, exports, module) {\
+ module.exports = parent.parent.require("/plugins");\
+ });\
+</script>\
+');
+ pushScriptsTo(iframeHTML);
+
iframeHTML.push('<style type="text/css" title="dynamicsyntax"></style>');
iframeHTML.push('</head><body id="innerdocbody" class="syntax" spellcheck="false">&nbsp;</body></html>');
- editor.iframeHTML = iframeHTML.join('\n');
-
// Expose myself to global for my child frame.
var thisFunctionsName = "ChildAccessibleAce2Editor";
(function () {return this}())[thisFunctionsName] = Ace2Editor;
-
- var outerScript = 'editorId = "' + info.id + '"; editorInfo = parent.' + thisFunctionsName + '.registry[editorId]; ' +
- 'window.onload = function()' +
- '{ window.onload = null; setTimeout' + '(function() ' +
- '{ var iframe = document.createElement("IFRAME"); ' +
- 'iframe.scrolling = "no"; var outerdocbody = document.getElementById("outerdocbody"); ' +
- 'iframe.frameBorder = 0; iframe.allowTransparency = true; ' + // for IE
- 'outerdocbody.insertBefore(iframe, outerdocbody.firstChild); ' +
- 'iframe.ace_outerWin = window; ' +
- 'var doc = iframe.contentWindow.document; doc.open();doc.write(editorInfo.editor.iframeHTML); doc.close();'+
- 'readyFunc = function() { editorInfo.onEditorReady(); readyFunc = null; editorInfo = null; };' +
- '}, 0); }';
-
-
- // Build HTML of editor iFrame;
- var outerHTML = [doctype, '<html><head>'];
- outerHTML.push('<link rel="stylesheet" type="text/css" href="../static/css/iframe_editor.css">');
- outerHTML.push('<link rel="stylesheet" type="text/css" href="../static/css/pad.css">');
- outerHTML.push('<link rel="stylesheet" type="text/css" href="../static/custom/pad.css"');
+ var outerScript = 'editorId = "' + info.id + '"; editorInfo = parent.' + thisFunctionsName + '.registry[editorId]; ' + 'window.onload = function() ' + '{ window.onload = null; setTimeout' + '(function() ' + '{ var iframe = document.createElement("IFRAME"); ' + 'iframe.scrolling = "no"; var outerdocbody = document.getElementById("outerdocbody"); ' + 'iframe.frameBorder = 0; iframe.allowTransparency = true; ' + // for IE
+ 'outerdocbody.insertBefore(iframe, outerdocbody.firstChild); ' + 'iframe.ace_outerWin = window; ' + 'readyFunc = function() { editorInfo.onEditorReady(); readyFunc = null; editorInfo = null; }; ' + 'var doc = iframe.contentWindow.document; doc.open(); var text = (' + JSON.stringify(iframeHTML.join('\n')) + ');doc.write(text); doc.close(); ' + '}, 0); }';
+
+ var outerHTML = [doctype, '<html><head>']
+
+ var includedCSS = [];
+ var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)};
+ $$INCLUDE_CSS("../static/css/iframe_editor.css");
+ $$INCLUDE_CSS("../static/css/pad.css");
+ $$INCLUDE_CSS("../static/custom/pad.css");
+ pushStyleTagsFor(outerHTML, includedCSS);
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
// (throbs busy while typing)
@@ -244,7 +295,6 @@ function Ace2Editor()
document.getElementById(containerId).appendChild(outerFrame);
var editorDocument = outerFrame.contentWindow.document;
-
editorDocument.open();
editorDocument.write(outerHTML.join(''));