diff options
author | Stefan <mu.stefan@googlemail.com> | 2015-04-11 12:10:37 +0200 |
---|---|---|
committer | Stefan <mu.stefan@googlemail.com> | 2015-04-11 12:10:37 +0200 |
commit | aa0d14c7d71da3d3c4f123e1577848c026bccf0b (patch) | |
tree | 19cc760c2aa04ab57eb23e500dc442c0a901a7d1 /src/static/js/contentcollector.js | |
parent | 573a912e4f1b481fca8f3c8146972e78f76278e2 (diff) | |
parent | cc34f4e325830f798321b8152095c4dccd6b465f (diff) | |
download | etherpad-lite-aa0d14c7d71da3d3c4f123e1577848c026bccf0b.zip |
Merge branch 'master' of git://github.com/ether/etherpad-lite into create_pad_special_characters
Diffstat (limited to 'src/static/js/contentcollector.js')
-rw-r--r-- | src/static/js/contentcollector.js | 103 |
1 files changed, 85 insertions, 18 deletions
diff --git a/src/static/js/contentcollector.js b/src/static/js/contentcollector.js index 5e393670..857e171f 100644 --- a/src/static/js/contentcollector.js +++ b/src/static/js/contentcollector.js @@ -23,7 +23,7 @@ * limitations under the License. */ -var _MAX_LIST_LEVEL = 8; +var _MAX_LIST_LEVEL = 16; var UNorm = require('unorm'); var Changeset = require('./Changeset'); @@ -32,12 +32,13 @@ var _ = require('./underscore'); function sanitizeUnicode(s) { - return UNorm.nfc(s).replace(/[\uffff\ufffe\ufeff\ufdd0-\ufdef\ud800-\udfff]/g, '?'); + return UNorm.nfc(s); } -function makeContentCollector(collectStyles, browser, apool, domInterface, className2Author) +function makeContentCollector(collectStyles, abrowser, apool, domInterface, className2Author) { - browser = browser || {}; + abrowser = abrowser || {}; + // I don't like the above. var dom = domInterface || { isNodeText: function(n) @@ -54,10 +55,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class }, nodeNumChildren: function(n) { + if(n.childNodes == null) return 0; return n.childNodes.length; }, nodeChild: function(n, i) { + if(n.childNodes.item == null){ + return n.childNodes[i]; + } return n.childNodes.item(i); }, nodeProp: function(n, p) @@ -66,6 +71,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class }, nodeAttr: function(n, a) { + if(n.getAttribute == null) return null; return n.getAttribute(a); }, optNodeInnerHTML: function(n) @@ -81,6 +87,10 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class "li": 1 }; + _.each(hooks.callAll('ccRegisterBlockElements'), function(element){ + _blockElems[element] = 1; + }); + function isBlockElement(n) { return !!_blockElems[(dom.nodeTagName(n) || "").toLowerCase()]; @@ -287,7 +297,23 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class { if (state.attribs[a]) { - lst.push([a, 'true']); + // The following splitting of the attribute name is a workaround + // to enable the content collector to store key-value attributes + // see https://github.com/ether/etherpad-lite/issues/2567 for more information + // in long term the contentcollector should be refactored to get rid of this workaround + var ATTRIBUTE_SPLIT_STRING = "::"; + + // see if attributeString is splittable + var attributeSplits = a.split(ATTRIBUTE_SPLIT_STRING); + if (attributeSplits.length > 1) { + // the attribute name follows the convention key::value + // so save it as a key value attribute + lst.push([attributeSplits[0], attributeSplits[1]]); + } else { + // the "normal" case, the attribute is just a switch + // so set it true + lst.push([a, 'true']); + } } } if (state.authorLevel > 0) @@ -314,7 +340,6 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class return [key, value]; }) ); - lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool)); } cc.startNewLine = function(state) @@ -452,8 +477,23 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class else { var tname = (dom.nodeTagName(node) || "").toLowerCase(); + + if (tname == "img"){ + var collectContentImage = hooks.callAll('collectContentImage', { + cc: cc, + state: state, + tname: tname, + styl: styl, + cls: cls, + node: node + }); + }else{ + // THIS SEEMS VERY HACKY! -- Please submit a better fix! + delete state.lineAttributes.img + } + if (tname == "br") - { + { this.breakLine = true; var tvalue = dom.nodeAttr(node, 'value'); var induceLineBreak = hooks.callAll('collectContentLineBreak', { @@ -477,9 +517,8 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class { var styl = dom.nodeAttr(node, "style"); var cls = dom.nodeProp(node, "className"); - var isPre = (tname == "pre"); - if ((!isPre) && browser.safari) + if ((!isPre) && abrowser.safari) { isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl)); } @@ -513,14 +552,44 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class } if (tname == "ul" || tname == "ol") { - var type; - var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls); - type = rr && rr[1] || (tname == "ul" ? "bullet" : "number") + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); + if(node.attribs){ + var type = node.attribs.class; + }else{ + var type = null; + } + var rr = cls && /(?:^| )list-([a-z]+[0-9]+)\b/.exec(cls); + // lists do not need to have a type, so before we make a wrong guess, check if we find a better hint within the node's children + if(!rr && !type){ + for (var i in node.children){ + if(node.children[i] && node.children[i].name=='ul'){ + type = node.children[i].attribs.class + if(type){ + break + } + } + } + } + if(rr && rr[1]){ + type = rr[1] + } else { + if(tname == "ul"){ + if((type && type.match("indent")) || (node.attribs && node.attribs.class && node.attribs.class.match("indent"))){ + type = "indent" + } else { + type = "bullet" + } + } else { + type = "number" + } + type = type + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); + } oldListTypeOrNull = (_enterList(state, type) || 'none'); } else if ((tname == "div" || tname == "p") && cls && cls.match(/(?:^| )ace-line\b/)) { - oldListTypeOrNull = (_enterList(state, type) || 'none'); + // This has undesirable behavior in Chrome but is right in other browsers. + // See https://github.com/ether/etherpad-lite/issues/2412 for reasoning + if(!abrowser.chrome) oldListTypeOrNull = (_enterList(state, type) || 'none'); } if (className2Author && cls) { @@ -577,7 +646,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class } } } - if (!browser.msie) + if (!abrowser.msie) { _reachBlockPoint(node, 1, state); } @@ -592,13 +661,11 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class _ensureColumnZero(state); } } - - if (browser.msie) + if (abrowser.msie) { // in IE, a point immediately after a DIV appears on the next line _reachBlockPoint(node, 1, state); } - state.localAttribs = localAttribs; }; // can pass a falsy value for end of doc @@ -663,7 +730,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class { //var semiloc = oldString.lastIndexOf(';', lineLimit-1); //var lengthToTake = (semiloc >= 0 ? (semiloc+1) : lineLimit); - lengthToTake = lineLimit; + var lengthToTake = lineLimit; newStrings.push(oldString.substring(0, lengthToTake)); oldString = oldString.substring(lengthToTake); newAttribStrings.push(Changeset.subattribution(oldAttribString, 0, lengthToTake)); |