diff options
author | John McLear <john@mclear.co.uk> | 2012-02-26 14:49:13 +0000 |
---|---|---|
committer | John McLear <john@mclear.co.uk> | 2012-02-26 14:49:13 +0000 |
commit | aa78456ab93e8e1eaffb240147ce6cbe7715a000 (patch) | |
tree | b5f0fe645c244ff2fbee0728a3983f5fa94ad0ff | |
parent | 8d764cad33b7f8be7b5883b965c95d4dcbce6ffa (diff) | |
download | etherpad-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.js | 74 | ||||
-rw-r--r-- | static/js/ace.js | 160 |
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"> </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('')); |