From aa78456ab93e8e1eaffb240147ce6cbe7715a000 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 26 Feb 2012 14:49:13 +0000 Subject: [PATCH 1/3] 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. --- node/utils/Minify.js | 74 +++++++++++++++++++- static/js/ace.js | 158 ++++++++++++++++++++++++++++--------------- 2 files changed, 176 insertions(+), 56 deletions(-) diff --git a/node/utils/Minify.js b/node/utils/Minify.js index baeaee688..859ee07ae 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 63b1e61fe..6c7bb84e2 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(''); - iframeHTML.push(''); - iframeHTML.push('\ +'); + pushScriptsTo(iframeHTML); + iframeHTML.push(''); iframeHTML.push(' '); - 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, '']; - outerHTML.push(''); - outerHTML.push(''); - outerHTML.push(''] + + 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('')); From 9fe4318e77ea348e3ebd287ede7cc3f41a1191c0 Mon Sep 17 00:00:00 2001 From: Constantin Jucovschi Date: Sun, 26 Feb 2012 18:59:11 +0000 Subject: [PATCH 2/3] more doc update --- static/js/Changeset.js | 174 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 8 deletions(-) diff --git a/static/js/Changeset.js b/static/js/Changeset.js index 42a8f0dc1..81c0c81b2 100644 --- a/static/js/Changeset.js +++ b/static/js/Changeset.js @@ -627,7 +627,11 @@ exports.stringAssembler = function () { }; }; -// "lines" need not be an array as long as it supports certain calls (lines_foo inside). +/** + * This class allows to iterate and modify texts which have several lines + * It is used for applying Changesets on arrays of lines + * Note from prev docs: "lines" need not be an array as long as it supports certain calls (lines_foo inside). + */ exports.textLinesMutator = function (lines) { // Mutates lines, an array of strings, in place. // Mutation operations have the same constraints as exports operations @@ -882,6 +886,21 @@ exports.textLinesMutator = function (lines) { return self; }; +/** + * Function allowing iterating over two Op strings. + * @params in1 {string} first Op string + * @params idx1 {int} integer where 1st iterator should start + * @params in2 {string} second Op string + * @params idx2 {int} integer where 2nd iterator should start + * @params func {function} which decides how 1st or 2nd iterator + * advances. When opX.opcode = 0, iterator X advances to + * next element + * func has signature f(op1, op2, opOut) + * op1 - current operation of the first iterator + * op2 - current operation of the second iterator + * opOut - result operator to be put into Changeset + * @return {string} the integrated changeset + */ exports.applyZip = function (in1, idx1, in2, idx2, func) { var iter1 = exports.opIterator(in1, idx1); var iter2 = exports.opIterator(in2, idx2); @@ -975,6 +994,11 @@ exports.applyToText = function (cs, str) { return assem.toString(); }; +/** + * applies a changeset on an array of lines + * @param CS {Changeset} the changeset to be applied + * @param lines The lines to which the changeset needs to be applied + */ exports.mutateTextLines = function (cs, lines) { var unpacked = exports.unpack(cs); var csIter = exports.opIterator(unpacked.ops); @@ -997,6 +1021,13 @@ exports.mutateTextLines = function (cs, lines) { mut.close(); }; +/** + * Composes two attribute strings (see below) into one. + * @param att1 {string} first attribute string + * @param att2 {string} second attribue string + * @param resultIsMutaton {boolean} + * @param pool {AttribPool} attribute pool + */ exports.composeAttributes = function (att1, att2, resultIsMutation, pool) { // att1 and att2 are strings like "*3*f*1c", asMutation is a boolean. // Sometimes attribute (key,value) pairs are treated as attribute presence @@ -1054,6 +1085,10 @@ exports.composeAttributes = function (att1, att2, resultIsMutation, pool) { return buf.toString(); }; +/** + * Function used as parameter for applyZip to apply a Changeset to an + * attribute + */ exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) { // attOp is the op from the sequence that is being operated on, either an // attribution string or the earlier of two exportss being composed. @@ -1140,6 +1175,12 @@ exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) { } }; +/** + * Applies a Changeset to the attribs string of a AText. + * @param cs {string} Changeset + * @param astr {string} the attribs string of a AText + * @param pool {AttribsPool} the attibutes pool + */ exports.applyToAttribution = function (cs, astr, pool) { var unpacked = exports.unpack(cs); @@ -1248,6 +1289,11 @@ exports.mutateAttributionLines = function (cs, lines, pool) { //dmesg("-> "+lines.toSource()); }; +/** + * joins several Attribution lines + * @param theAlines collection of Attribution lines + * @returns {string} joined Attribution lines + */ exports.joinAttributionLines = function (theAlines) { var assem = exports.mergingOpAssembler(); for (var i = 0; i < theAlines.length; i++) { @@ -1298,10 +1344,20 @@ exports.splitAttributionLines = function (attrOps, text) { return lines; }; +/** + * splits text into lines + * @param {string} text to be splitted + */ exports.splitTextLines = function (text) { return text.match(/[^\n]*(?:\n|[^\n]$)/g); }; +/** + * compose two Changesets + * @param cs1 {Changeset} first Changeset + * @param cs2 {Changeset} second Changeset + * @param pool {AtribsPool} Attribs pool + */ exports.compose = function (cs1, cs2, pool) { var unpacked1 = exports.unpack(cs1); var unpacked2 = exports.unpack(cs2); @@ -1344,10 +1400,14 @@ exports.compose = function (cs1, cs2, pool) { return exports.pack(len1, len3, newOps, bankAssem.toString()); }; +/** + * returns a function that tests if a string of attributes + * (e.g. *3*4) contains a given attribute key,value that + * is already present in the pool. + * @param attribPair array [key,value] of the attribute + * @param pool {AttribPool} Attribute pool + */ exports.attributeTester = function (attribPair, pool) { - // returns a function that tests if a string of attributes - // (e.g. *3*4) contains a given attribute key,value that - // is already present in the pool. if (!pool) { return never; } @@ -1366,10 +1426,27 @@ exports.attributeTester = function (attribPair, pool) { } }; +/** + * creates the identity Changeset of length N + * @param N {int} length of the identity changeset + */ exports.identity = function (N) { return exports.pack(N, N, "", ""); }; + +/** + * creates a Changeset which works on oldFullText and removes text + * from spliceStart to spliceStart+numRemoved and inserts newText + * instead. Also gives possibility to add attributes optNewTextAPairs + * for the new text. + * @param oldFullText {string} old text + * @param spliecStart {int} where splicing starts + * @param numRemoved {int} number of characters to be removed + * @param newText {string} string to be inserted + * @param optNewTextAPairs {string} new pairs to be inserted + * @param pool {AttribPool} Attribution Pool + */ exports.makeSplice = function (oldFullText, spliceStart, numRemoved, newText, optNewTextAPairs, pool) { var oldLen = oldFullText.length; @@ -1390,8 +1467,14 @@ exports.makeSplice = function (oldFullText, spliceStart, numRemoved, newText, op return exports.pack(oldLen, newLen, assem.toString(), newText); }; +/** + * Transforms a changeset into a list of splices in the form + * [startChar, endChar, newText] meaning replace text from + * startChar to endChar with newText + * @param cs Changeset + */ exports.toSplices = function (cs) { - // get a list of splices, [startChar, endChar, newText] + // var unpacked = exports.unpack(cs); var splices = []; @@ -1421,6 +1504,9 @@ exports.toSplices = function (cs) { return splices; }; +/** + * + */ exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter) { var newStartChar = startChar; var newEndChar = endChar; @@ -1465,6 +1551,14 @@ exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter return [newStartChar, newEndChar]; }; +/** + * Iterate over attributes in a changeset and move them from + * oldPool to newPool + * @param cs {Changeset} Chageset/attribution string to be iterated over + * @param oldPool {AttribPool} old attributes pool + * @param newPool {AttribPool} new attributes pool + * @return {string} the new Changeset + */ exports.moveOpsToNewPool = function (cs, oldPool, newPool) { // works on exports or attribution string var dollarPos = cs.indexOf('$'); @@ -1482,13 +1576,22 @@ exports.moveOpsToNewPool = function (cs, oldPool, newPool) { }) + fromDollar; }; +/** + * create an attribution inserting a text + * @param text {string} text to be inserted + */ exports.makeAttribution = function (text) { var assem = exports.smartOpAssembler(); assem.appendOpWithText('+', text); return assem.toString(); }; -// callable on a exports, attribution string, or attribs property of an op +/** + * Iterates over attributes in exports, attribution string, or attribs property of an op + * and runs function func on them + * @param cs {Changeset} changeset + * @param func {function} function to be called + */ exports.eachAttribNumber = function (cs, func) { var dollarPos = cs.indexOf('$'); if (dollarPos < 0) { @@ -1502,12 +1605,21 @@ exports.eachAttribNumber = function (cs, func) { }); }; -// callable on a exports, attribution string, or attribs property of an op, -// though it may easily create adjacent ops that can be merged. +/** + * Filter attributes which should remain in a Changeset + * callable on a exports, attribution string, or attribs property of an op, + * though it may easily create adjacent ops that can be merged. + * @param cs {Changeset} changeset to be filtered + * @param filter {function} fnc which returns true if an + * attribute X (int) should be kept in the Changeset + */ exports.filterAttribNumbers = function (cs, filter) { return exports.mapAttribNumbers(cs, filter); }; +/** + * does exactly the same as exports.filterAttribNumbers + */ exports.mapAttribNumbers = function (cs, func) { var dollarPos = cs.indexOf('$'); if (dollarPos < 0) { @@ -1542,6 +1654,12 @@ exports.makeAText = function (text, attribs) { }; }; +/** + * Apply a Changeset to a AText + * @param cs {Changeset} Changeset to be applied + * @param atext {AText} + * @param pool {AttribPool} Attribute Pool to add to + */ exports.applyToAText = function (cs, atext, pool) { return { text: exports.applyToText(cs, atext.text), @@ -1549,6 +1667,10 @@ exports.applyToAText = function (cs, atext, pool) { }; }; +/** + * Clones a AText structure + * @param atext {AText} + */ exports.cloneAText = function (atext) { return { text: atext.text, @@ -1556,11 +1678,20 @@ exports.cloneAText = function (atext) { }; }; +/** + * Copies a AText structure from atext1 to atext2 + * @param atext {AText} + */ exports.copyAText = function (atext1, atext2) { atext2.text = atext1.text; atext2.attribs = atext1.attribs; }; +/** + * Append the set of operations from atext to an assembler + * @param atext {AText} + * @param assem Assembler like smartOpAssembler + */ exports.appendATextToAssembler = function (atext, assem) { // intentionally skips last newline char of atext var iter = exports.opIterator(atext.attribs); @@ -1594,6 +1725,11 @@ exports.appendATextToAssembler = function (atext, assem) { } }; +/** + * Creates a clone of a Changeset and it's APool + * @param cs {Changeset} + * @param pool {AtributePool} + */ exports.prepareForWire = function (cs, pool) { var newPool = AttributePoolFactory.createAttributePool();; var newCs = exports.moveOpsToNewPool(cs, pool, newPool); @@ -1603,15 +1739,32 @@ exports.prepareForWire = function (cs, pool) { }; }; +/** + * Checks if a changeset s the identity changeset + */ exports.isIdentity = function (cs) { var unpacked = exports.unpack(cs); return unpacked.ops == "" && unpacked.oldLen == unpacked.newLen; }; +/** + * returns all the values of attributes with a certain key + * in an Op attribs string + * @param attribs {string} Attribute string of a Op + * @param key {string} string to be seached for + * @param pool {AttribPool} attribute pool + */ exports.opAttributeValue = function (op, key, pool) { return exports.attribsAttributeValue(op.attribs, key, pool); }; +/** + * returns all the values of attributes with a certain key + * in an attribs string + * @param attribs {string} Attribute string + * @param key {string} string to be seached for + * @param pool {AttribPool} attribute pool + */ exports.attribsAttributeValue = function (attribs, key, pool) { var value = ''; if (attribs) { @@ -1624,6 +1777,11 @@ exports.attribsAttributeValue = function (attribs, key, pool) { return value; }; +/** + * Creates a Changeset builder for a string with initial + * length oldLen. Allows to add/remove parts of it + * @param oldLen {int} Old length + */ exports.builder = function (oldLen) { var assem = exports.smartOpAssembler(); var o = exports.newOp(); From 4dc86f338224dff193f2bfe131a66e893dee2550 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 26 Feb 2012 21:26:42 +0000 Subject: [PATCH 3/3] fix #507 import showing when it shouldnt --- static/js/pad_impexp.js | 1 + 1 file changed, 1 insertion(+) diff --git a/static/js/pad_impexp.js b/static/js/pad_impexp.js index 6fe42c705..130281bfa 100644 --- a/static/js/pad_impexp.js +++ b/static/js/pad_impexp.js @@ -257,6 +257,7 @@ var padimpexp = (function() $("#exportworda").remove(); $("#exportpdfa").remove(); $("#exportopena").remove(); + $(".importformdiv").remove(); $("#import").html("Import is not available. To enable import please install abiword"); } else if(clientVars.abiwordAvailable == "withoutPDF")