This commit is contained in:
Egil Moeller 2015-04-25 19:56:22 +02:00
parent 90b359c82b
commit 61e0442ec7
6 changed files with 6128 additions and 6103 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -26,296 +26,300 @@
// requires: plugins // requires: plugins
// requires: undefined // requires: undefined
var Security = require('./security'); define(['ep_etherpad-lite/static/js/pluginfw/hooks', 'ep_etherpad-lite/static/js/linestylefilter', 'underscore'], function(hooks, linestylefilterMod, _) {
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); var exports = {};
var _ = require('./underscore');
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker; var Security = require('./security');
var noop = function(){}; var lineAttributeMarker = linestylefilterMod.lineAttributeMarker;
var noop = function(){};
var domline = {}; var domline = {};
domline.addToLineClass = function(lineClass, cls) domline.addToLineClass = function(lineClass, cls)
{
// an "empty span" at any point can be used to add classes to
// the line, using line:className. otherwise, we ignore
// the span.
cls.replace(/\S+/g, function(c)
{ {
if (c.indexOf("line:") == 0) // an "empty span" at any point can be used to add classes to
// the line, using line:className. otherwise, we ignore
// the span.
cls.replace(/\S+/g, function(c)
{ {
// add class to line if (c.indexOf("line:") == 0)
lineClass = (lineClass ? lineClass + ' ' : '') + c.substring(5); {
} // add class to line
}); lineClass = (lineClass ? lineClass + ' ' : '') + c.substring(5);
return lineClass; }
} });
return lineClass;
// if "document" is falsy we don't create a DOM node, just
// an object with innerHTML and className
domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
{
var result = {
node: null,
appendSpan: noop,
prepareForAdd: noop,
notifyAdded: noop,
clearSpans: noop,
finishUpdate: noop,
lineMarker: 0
};
var document = optDocument;
if (document)
{
result.node = document.createElement("div");
} }
else
// if "document" is falsy we don't create a DOM node, just
// an object with innerHTML and className
domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
{ {
result.node = { var result = {
innerHTML: '', node: null,
className: '' appendSpan: noop,
prepareForAdd: noop,
notifyAdded: noop,
clearSpans: noop,
finishUpdate: noop,
lineMarker: 0
}; };
}
var html = []; var document = optDocument;
var preHtml = '',
postHtml = '';
var curHTML = null;
function processSpaces(s) if (document)
{
return domline.processSpaces(s, doesWrap);
}
var perTextNodeProcess = (doesWrap ? _.identity : processSpaces);
var perHtmlLineProcess = (doesWrap ? processSpaces : _.identity);
var lineClass = 'ace-line';
result.appendSpan = function(txt, cls)
{
var processedMarker = false;
// Handle lineAttributeMarker, if present
if (cls.indexOf(lineAttributeMarker) >= 0)
{ {
var listType = /(?:^| )list:(\S+)/.exec(cls); result.node = document.createElement("div");
var start = /(?:^| )start:(\S+)/.exec(cls); }
else
{
result.node = {
innerHTML: '',
className: ''
};
}
_.map(hooks.callAll("aceDomLinePreProcessLineAttributes", { var html = [];
domline: domline, var preHtml = '',
cls: cls postHtml = '';
}), function(modifier) var curHTML = null;
{
preHtml += modifier.preHtml;
postHtml += modifier.postHtml;
processedMarker |= modifier.processedMarker;
});
if (listType) function processSpaces(s)
{
return domline.processSpaces(s, doesWrap);
}
var perTextNodeProcess = (doesWrap ? _.identity : processSpaces);
var perHtmlLineProcess = (doesWrap ? processSpaces : _.identity);
var lineClass = 'ace-line';
result.appendSpan = function(txt, cls)
{
var processedMarker = false;
// Handle lineAttributeMarker, if present
if (cls.indexOf(lineAttributeMarker) >= 0)
{ {
listType = listType[1]; var listType = /(?:^| )list:(\S+)/.exec(cls);
var start = /(?:^| )start:(\S+)/.exec(cls);
_.map(hooks.callAll("aceDomLinePreProcessLineAttributes", {
domline: domline,
cls: cls
}), function(modifier)
{
preHtml += modifier.preHtml;
postHtml += modifier.postHtml;
processedMarker |= modifier.processedMarker;
});
if (listType) if (listType)
{ {
if(listType.indexOf("number") < 0) listType = listType[1];
if (listType)
{ {
preHtml += '<ul class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>'; if(listType.indexOf("number") < 0)
postHtml = '</li></ul>' + postHtml; {
} preHtml += '<ul class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
else postHtml = '</li></ul>' + postHtml;
{
if(start){ // is it a start of a list with more than one item in?
if(start[1] == 1){ // if its the first one at this level?
lineClass = lineClass + " " + "list-start-" + listType; // Add start class to DIV node
}
preHtml += '<ol start='+start[1]+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
}else{
preHtml += '<ol class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>'; // Handles pasted contents into existing lists
} }
postHtml += '</li></ol>'; else
} {
if(start){ // is it a start of a list with more than one item in?
if(start[1] == 1){ // if its the first one at this level?
lineClass = lineClass + " " + "list-start-" + listType; // Add start class to DIV node
}
preHtml += '<ol start='+start[1]+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
}else{
preHtml += '<ol class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>'; // Handles pasted contents into existing lists
}
postHtml += '</li></ol>';
}
}
processedMarker = true;
}
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
domline: domline,
cls: cls
}), function(modifier)
{
preHtml += modifier.preHtml;
postHtml += modifier.postHtml;
processedMarker |= modifier.processedMarker;
});
if( processedMarker ){
result.lineMarker += txt.length;
return; // don't append any text
} }
processedMarker = true;
} }
_.map(hooks.callAll("aceDomLineProcessLineAttributes", { var href = null;
var simpleTags = null;
if (cls.indexOf('url') >= 0)
{
cls = cls.replace(/(^| )url:(\S+)/g, function(x0, space, url)
{
href = url;
return space + "url";
});
}
if (cls.indexOf('tag') >= 0)
{
cls = cls.replace(/(^| )tag:(\S+)/g, function(x0, space, tag)
{
if (!simpleTags) simpleTags = [];
simpleTags.push(tag.toLowerCase());
return space + tag;
});
}
var extraOpenTags = "";
var extraCloseTags = "";
_.map(hooks.callAll("aceCreateDomLine", {
domline: domline, domline: domline,
cls: cls cls: cls
}), function(modifier) }), function(modifier)
{ {
preHtml += modifier.preHtml; cls = modifier.cls;
postHtml += modifier.postHtml; extraOpenTags = extraOpenTags + modifier.extraOpenTags;
processedMarker |= modifier.processedMarker; extraCloseTags = modifier.extraCloseTags + extraCloseTags;
}); });
if( processedMarker ){
result.lineMarker += txt.length;
return; // don't append any text
}
}
var href = null;
var simpleTags = null;
if (cls.indexOf('url') >= 0)
{
cls = cls.replace(/(^| )url:(\S+)/g, function(x0, space, url)
{
href = url;
return space + "url";
});
}
if (cls.indexOf('tag') >= 0)
{
cls = cls.replace(/(^| )tag:(\S+)/g, function(x0, space, tag)
{
if (!simpleTags) simpleTags = [];
simpleTags.push(tag.toLowerCase());
return space + tag;
});
}
var extraOpenTags = ""; if ((!txt) && cls)
var extraCloseTags = "";
_.map(hooks.callAll("aceCreateDomLine", {
domline: domline,
cls: cls
}), function(modifier)
{
cls = modifier.cls;
extraOpenTags = extraOpenTags + modifier.extraOpenTags;
extraCloseTags = modifier.extraCloseTags + extraCloseTags;
});
if ((!txt) && cls)
{
lineClass = domline.addToLineClass(lineClass, cls);
}
else if (txt)
{
if (href)
{ {
if(!~href.indexOf("://") && !~href.indexOf("mailto:")) // if the url doesn't include a protocol prefix, assume http lineClass = domline.addToLineClass(lineClass, cls);
}
else if (txt)
{
if (href)
{ {
href = "http://"+href; if(!~href.indexOf("://") && !~href.indexOf("mailto:")) // if the url doesn't include a protocol prefix, assume http
{
href = "http://"+href;
}
extraOpenTags = extraOpenTags + '<a href="' + Security.escapeHTMLAttribute(href) + '">';
extraCloseTags = '</a>' + extraCloseTags;
} }
extraOpenTags = extraOpenTags + '<a href="' + Security.escapeHTMLAttribute(href) + '">'; if (simpleTags)
extraCloseTags = '</a>' + extraCloseTags; {
simpleTags.sort();
extraOpenTags = extraOpenTags + '<' + simpleTags.join('><') + '>';
simpleTags.reverse();
extraCloseTags = '</' + simpleTags.join('></') + '>' + extraCloseTags;
}
html.push('<span class="', Security.escapeHTMLAttribute(cls || ''), '">', extraOpenTags, perTextNodeProcess(Security.escapeHTML(txt)), extraCloseTags, '</span>');
} }
if (simpleTags) };
result.clearSpans = function()
{
html = [];
lineClass = ''; // non-null to cause update
result.lineMarker = 0;
};
function writeHTML()
{
var newHTML = perHtmlLineProcess(html.join(''));
if (!newHTML)
{ {
simpleTags.sort(); if ((!document) || (!optBrowser))
extraOpenTags = extraOpenTags + '<' + simpleTags.join('><') + '>'; {
simpleTags.reverse(); newHTML += '&nbsp;';
extraCloseTags = '</' + simpleTags.join('></') + '>' + extraCloseTags; }
else if (!optBrowser.msie)
{
newHTML += '<br/>';
}
} }
html.push('<span class="', Security.escapeHTMLAttribute(cls || ''), '">', extraOpenTags, perTextNodeProcess(Security.escapeHTML(txt)), extraCloseTags, '</span>'); if (nonEmpty)
{
newHTML = (preHtml || '') + newHTML + (postHtml || '');
}
html = preHtml = postHtml = ''; // free memory
if (newHTML !== curHTML)
{
curHTML = newHTML;
result.node.innerHTML = curHTML;
}
if (lineClass !== null) result.node.className = lineClass;
hooks.callAll("acePostWriteDomLineHTML", {
node: result.node
});
} }
}; result.prepareForAdd = writeHTML;
result.clearSpans = function() result.finishUpdate = writeHTML;
{ result.getInnerHTML = function()
html = []; {
lineClass = ''; // non-null to cause update return curHTML || '';
result.lineMarker = 0; };
return result;
}; };
function writeHTML() domline.processSpaces = function(s, doesWrap)
{ {
var newHTML = perHtmlLineProcess(html.join('')); if (s.indexOf("<") < 0 && !doesWrap)
if (!newHTML)
{ {
if ((!document) || (!optBrowser)) // short-cut
{ return s.replace(/ /g, '&nbsp;');
newHTML += '&nbsp;';
}
else if (!optBrowser.msie)
{
newHTML += '<br/>';
}
} }
if (nonEmpty) var parts = [];
s.replace(/<[^>]*>?| |[^ <]+/g, function(m)
{ {
newHTML = (preHtml || '') + newHTML + (postHtml || ''); parts.push(m);
}
html = preHtml = postHtml = ''; // free memory
if (newHTML !== curHTML)
{
curHTML = newHTML;
result.node.innerHTML = curHTML;
}
if (lineClass !== null) result.node.className = lineClass;
hooks.callAll("acePostWriteDomLineHTML", {
node: result.node
}); });
} if (doesWrap)
result.prepareForAdd = writeHTML; {
result.finishUpdate = writeHTML; var endOfLine = true;
result.getInnerHTML = function() var beforeSpace = false;
{ // last space in a run is normal, others are nbsp,
return curHTML || ''; // end of line is nbsp
for (var i = parts.length - 1; i >= 0; i--)
{
var p = parts[i];
if (p == " ")
{
if (endOfLine || beforeSpace) parts[i] = '&nbsp;';
endOfLine = false;
beforeSpace = true;
}
else if (p.charAt(0) != "<")
{
endOfLine = false;
beforeSpace = false;
}
}
// beginning of line is nbsp
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
break;
}
else if (p.charAt(0) != "<")
{
break;
}
}
}
else
{
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
}
}
}
return parts.join('');
}; };
return result;
};
domline.processSpaces = function(s, doesWrap) exports.domline = domline;
{
if (s.indexOf("<") < 0 && !doesWrap)
{
// short-cut
return s.replace(/ /g, '&nbsp;');
}
var parts = [];
s.replace(/<[^>]*>?| |[^ <]+/g, function(m)
{
parts.push(m);
});
if (doesWrap)
{
var endOfLine = true;
var beforeSpace = false;
// last space in a run is normal, others are nbsp,
// end of line is nbsp
for (var i = parts.length - 1; i >= 0; i--)
{
var p = parts[i];
if (p == " ")
{
if (endOfLine || beforeSpace) parts[i] = '&nbsp;';
endOfLine = false;
beforeSpace = true;
}
else if (p.charAt(0) != "<")
{
endOfLine = false;
beforeSpace = false;
}
}
// beginning of line is nbsp
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
break;
}
else if (p.charAt(0) != "<")
{
break;
}
}
}
else
{
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
}
}
}
return parts.join('');
};
exports.domline = domline; return exports;
});

View file

@ -28,338 +28,342 @@
// requires: plugins // requires: plugins
// requires: undefined // requires: undefined
var Changeset = require('./Changeset'); define(['ep_etherpad-lite/static/js/pluginfw/hooks', 'underscore'], function (hooks, _) {
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); var exports = {};
var linestylefilter = {};
var _ = require('./underscore');
var AttributeManager = require('./AttributeManager');
linestylefilter.ATTRIB_CLASSES = { var Changeset = require('./Changeset');
'bold': 'tag:b', var linestylefilter = {};
'italic': 'tag:i', var AttributeManager = require('./AttributeManager');
'underline': 'tag:u',
'strikethrough': 'tag:s'
};
var lineAttributeMarker = 'lineAttribMarker'; linestylefilter.ATTRIB_CLASSES = {
exports.lineAttributeMarker = lineAttributeMarker; 'bold': 'tag:b',
'italic': 'tag:i',
'underline': 'tag:u',
'strikethrough': 'tag:s'
};
linestylefilter.getAuthorClassName = function(author) var lineAttributeMarker = 'lineAttribMarker';
{ exports.lineAttributeMarker = lineAttributeMarker;
return "author-" + author.replace(/[^a-y0-9]/g, function(c)
linestylefilter.getAuthorClassName = function(author)
{ {
if (c == ".") return "-"; return "author-" + author.replace(/[^a-y0-9]/g, function(c)
return 'z' + c.charCodeAt(0) + 'z';
});
};
// lineLength is without newline; aline includes newline,
// but may be falsy if lineLength == 0
linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFunc, apool)
{
// Plugin Hook to add more Attrib Classes
hooks.aCallAll('aceAttribClasses', linestylefilter.ATTRIB_CLASSES, function(err, ATTRIB_CLASSES){
if(ATTRIB_CLASSES.length >= 1){
linestylefilter.ATTRIB_CLASSES = ATTRIB_CLASSES[0];
}
});
if (lineLength == 0) return textAndClassFunc;
var nextAfterAuthorColors = textAndClassFunc;
var authorColorFunc = (function()
{
var lineEnd = lineLength;
var curIndex = 0;
var extraClasses;
var leftInAuthor;
function attribsToClasses(attribs)
{ {
var classes = ''; if (c == ".") return "-";
var isLineAttribMarker = false; return 'z' + c.charCodeAt(0) + 'z';
});
Changeset.eachAttribNumber(attribs, function(n) };
// lineLength is without newline; aline includes newline,
// but may be falsy if lineLength == 0
linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFunc, apool)
{
// Plugin Hook to add more Attrib Classes
hooks.aCallAll('aceAttribClasses', linestylefilter.ATTRIB_CLASSES, function(err, ATTRIB_CLASSES){
if(ATTRIB_CLASSES.length >= 1){
linestylefilter.ATTRIB_CLASSES = ATTRIB_CLASSES[0];
}
});
if (lineLength == 0) return textAndClassFunc;
var nextAfterAuthorColors = textAndClassFunc;
var authorColorFunc = (function()
{
var lineEnd = lineLength;
var curIndex = 0;
var extraClasses;
var leftInAuthor;
function attribsToClasses(attribs)
{ {
var key = apool.getAttribKey(n); var classes = '';
if (key) var isLineAttribMarker = false;
Changeset.eachAttribNumber(attribs, function(n)
{ {
var value = apool.getAttribValue(n); var key = apool.getAttribKey(n);
if (value) if (key)
{ {
if (!isLineAttribMarker && _.indexOf(AttributeManager.lineAttributes, key) >= 0){ var value = apool.getAttribValue(n);
isLineAttribMarker = true; if (value)
}
if (key == 'author')
{ {
classes += ' ' + linestylefilter.getAuthorClassName(value); if (!isLineAttribMarker && _.indexOf(AttributeManager.lineAttributes, key) >= 0){
isLineAttribMarker = true;
}
if (key == 'author')
{
classes += ' ' + linestylefilter.getAuthorClassName(value);
}
else if (key == 'list')
{
classes += ' list:' + value;
}
else if (key == 'start')
{
classes += ' start:' + value;
}
else if (linestylefilter.ATTRIB_CLASSES[key])
{
classes += ' ' + linestylefilter.ATTRIB_CLASSES[key];
}
else
{
classes += hooks.callAllStr("aceAttribsToClasses", {
linestylefilter: linestylefilter,
key: key,
value: value
}, " ", " ", "");
}
} }
else if (key == 'list') }
{ });
classes += ' list:' + value;
} if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
else if (key == 'start') return classes.substring(1);
{ }
classes += ' start:' + value;
} var attributionIter = Changeset.opIterator(aline);
else if (linestylefilter.ATTRIB_CLASSES[key]) var nextOp, nextOpClasses;
{
classes += ' ' + linestylefilter.ATTRIB_CLASSES[key]; function goNextOp()
} {
else nextOp = attributionIter.next();
{ nextOpClasses = (nextOp.opcode && attribsToClasses(nextOp.attribs));
classes += hooks.callAllStr("aceAttribsToClasses", { }
linestylefilter: linestylefilter, goNextOp();
key: key,
value: value function nextClasses()
}, " ", " ", ""); {
} if (curIndex < lineEnd)
{
extraClasses = nextOpClasses;
leftInAuthor = nextOp.chars;
goNextOp();
while (nextOp.opcode && nextOpClasses == extraClasses)
{
leftInAuthor += nextOp.chars;
goNextOp();
} }
} }
});
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
return classes.substring(1);
}
var attributionIter = Changeset.opIterator(aline);
var nextOp, nextOpClasses;
function goNextOp()
{
nextOp = attributionIter.next();
nextOpClasses = (nextOp.opcode && attribsToClasses(nextOp.attribs));
}
goNextOp();
function nextClasses()
{
if (curIndex < lineEnd)
{
extraClasses = nextOpClasses;
leftInAuthor = nextOp.chars;
goNextOp();
while (nextOp.opcode && nextOpClasses == extraClasses)
{
leftInAuthor += nextOp.chars;
goNextOp();
}
} }
} nextClasses();
nextClasses();
return function(txt, cls)
{
var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
linestylefilter: linestylefilter,
text: txt,
"class": cls
}, " ", " ", "");
var disableAuthors = (disableAuthColorForThisLine==null||disableAuthColorForThisLine.length==0)?false:disableAuthColorForThisLine[0];
while (txt.length > 0)
{
if (leftInAuthor <= 0 || disableAuthors)
{
// prevent infinite loop if something funny's going on
return nextAfterAuthorColors(txt, cls);
}
var spanSize = txt.length;
if (spanSize > leftInAuthor)
{
spanSize = leftInAuthor;
}
var curTxt = txt.substring(0, spanSize);
txt = txt.substring(spanSize);
nextAfterAuthorColors(curTxt, (cls && cls + " ") + extraClasses);
curIndex += spanSize;
leftInAuthor -= spanSize;
if (leftInAuthor == 0)
{
nextClasses();
}
}
};
})();
return authorColorFunc;
};
linestylefilter.getAtSignSplitterFilter = function(lineText, textAndClassFunc)
{
var at = /@/g;
at.lastIndex = 0;
var splitPoints = null;
var execResult;
while ((execResult = at.exec(lineText)))
{
if (!splitPoints)
{
splitPoints = [];
}
splitPoints.push(execResult.index);
}
if (!splitPoints) return textAndClassFunc;
return linestylefilter.textAndClassFuncSplitter(textAndClassFunc, splitPoints);
};
linestylefilter.getRegexpFilter = function(regExp, tag)
{
return function(lineText, textAndClassFunc)
{
regExp.lastIndex = 0;
var regExpMatchs = null;
var splitPoints = null;
var execResult;
while ((execResult = regExp.exec(lineText)))
{
if (!regExpMatchs)
{
regExpMatchs = [];
splitPoints = [];
}
var startIndex = execResult.index;
var regExpMatch = execResult[0];
regExpMatchs.push([startIndex, regExpMatch]);
splitPoints.push(startIndex, startIndex + regExpMatch.length);
}
if (!regExpMatchs) return textAndClassFunc;
function regExpMatchForIndex(idx)
{
for (var k = 0; k < regExpMatchs.length; k++)
{
var u = regExpMatchs[k];
if (idx >= u[0] && idx < u[0] + u[1].length)
{
return u[1];
}
}
return false;
}
var handleRegExpMatchsAfterSplit = (function()
{
var curIndex = 0;
return function(txt, cls) return function(txt, cls)
{ {
var txtlen = txt.length;
var newCls = cls; var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
var regExpMatch = regExpMatchForIndex(curIndex); linestylefilter: linestylefilter,
if (regExpMatch) text: txt,
"class": cls
}, " ", " ", "");
var disableAuthors = (disableAuthColorForThisLine==null||disableAuthColorForThisLine.length==0)?false:disableAuthColorForThisLine[0];
while (txt.length > 0)
{ {
newCls += " " + tag + ":" + regExpMatch; if (leftInAuthor <= 0 || disableAuthors)
{
// prevent infinite loop if something funny's going on
return nextAfterAuthorColors(txt, cls);
}
var spanSize = txt.length;
if (spanSize > leftInAuthor)
{
spanSize = leftInAuthor;
}
var curTxt = txt.substring(0, spanSize);
txt = txt.substring(spanSize);
nextAfterAuthorColors(curTxt, (cls && cls + " ") + extraClasses);
curIndex += spanSize;
leftInAuthor -= spanSize;
if (leftInAuthor == 0)
{
nextClasses();
}
} }
textAndClassFunc(txt, newCls);
curIndex += txtlen;
}; };
})(); })();
return authorColorFunc;
return linestylefilter.textAndClassFuncSplitter(handleRegExpMatchsAfterSplit, splitPoints);
}; };
};
linestylefilter.getAtSignSplitterFilter = function(lineText, textAndClassFunc)
linestylefilter.REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
linestylefilter.REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=&#!;()\[\]$]/.source + '|' + linestylefilter.REGEX_WORDCHAR.source + ')');
linestylefilter.REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|nfs):\/\/|mailto:|www\.)/.source + linestylefilter.REGEX_URLCHAR.source + '*(?![:.,;])' + linestylefilter.REGEX_URLCHAR.source, 'g');
linestylefilter.getURLFilter = linestylefilter.getRegexpFilter(
linestylefilter.REGEX_URL, 'url');
linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt)
{
var nextPointIndex = 0;
var idx = 0;
// don't split at 0
while (splitPointsOpt && nextPointIndex < splitPointsOpt.length && splitPointsOpt[nextPointIndex] == 0)
{ {
nextPointIndex++; var at = /@/g;
} at.lastIndex = 0;
var splitPoints = null;
function spanHandler(txt, cls) var execResult;
{ while ((execResult = at.exec(lineText)))
if ((!splitPointsOpt) || nextPointIndex >= splitPointsOpt.length)
{ {
func(txt, cls); if (!splitPoints)
idx += txt.length; {
splitPoints = [];
}
splitPoints.push(execResult.index);
} }
else
if (!splitPoints) return textAndClassFunc;
return linestylefilter.textAndClassFuncSplitter(textAndClassFunc, splitPoints);
};
linestylefilter.getRegexpFilter = function(regExp, tag)
{
return function(lineText, textAndClassFunc)
{ {
var splitPoints = splitPointsOpt; regExp.lastIndex = 0;
var pointLocInSpan = splitPoints[nextPointIndex] - idx; var regExpMatchs = null;
var txtlen = txt.length; var splitPoints = null;
if (pointLocInSpan >= txtlen) var execResult;
while ((execResult = regExp.exec(lineText)))
{
if (!regExpMatchs)
{
regExpMatchs = [];
splitPoints = [];
}
var startIndex = execResult.index;
var regExpMatch = execResult[0];
regExpMatchs.push([startIndex, regExpMatch]);
splitPoints.push(startIndex, startIndex + regExpMatch.length);
}
if (!regExpMatchs) return textAndClassFunc;
function regExpMatchForIndex(idx)
{
for (var k = 0; k < regExpMatchs.length; k++)
{
var u = regExpMatchs[k];
if (idx >= u[0] && idx < u[0] + u[1].length)
{
return u[1];
}
}
return false;
}
var handleRegExpMatchsAfterSplit = (function()
{
var curIndex = 0;
return function(txt, cls)
{
var txtlen = txt.length;
var newCls = cls;
var regExpMatch = regExpMatchForIndex(curIndex);
if (regExpMatch)
{
newCls += " " + tag + ":" + regExpMatch;
}
textAndClassFunc(txt, newCls);
curIndex += txtlen;
};
})();
return linestylefilter.textAndClassFuncSplitter(handleRegExpMatchsAfterSplit, splitPoints);
};
};
linestylefilter.REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
linestylefilter.REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=&#!;()\[\]$]/.source + '|' + linestylefilter.REGEX_WORDCHAR.source + ')');
linestylefilter.REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|nfs):\/\/|mailto:|www\.)/.source + linestylefilter.REGEX_URLCHAR.source + '*(?![:.,;])' + linestylefilter.REGEX_URLCHAR.source, 'g');
linestylefilter.getURLFilter = linestylefilter.getRegexpFilter(
linestylefilter.REGEX_URL, 'url');
linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt)
{
var nextPointIndex = 0;
var idx = 0;
// don't split at 0
while (splitPointsOpt && nextPointIndex < splitPointsOpt.length && splitPointsOpt[nextPointIndex] == 0)
{
nextPointIndex++;
}
function spanHandler(txt, cls)
{
if ((!splitPointsOpt) || nextPointIndex >= splitPointsOpt.length)
{ {
func(txt, cls); func(txt, cls);
idx += txt.length; idx += txt.length;
if (pointLocInSpan == txtlen)
{
nextPointIndex++;
}
} }
else else
{ {
if (pointLocInSpan > 0) var splitPoints = splitPointsOpt;
var pointLocInSpan = splitPoints[nextPointIndex] - idx;
var txtlen = txt.length;
if (pointLocInSpan >= txtlen)
{ {
func(txt.substring(0, pointLocInSpan), cls); func(txt, cls);
idx += pointLocInSpan; idx += txt.length;
if (pointLocInSpan == txtlen)
{
nextPointIndex++;
}
}
else
{
if (pointLocInSpan > 0)
{
func(txt.substring(0, pointLocInSpan), cls);
idx += pointLocInSpan;
}
nextPointIndex++;
// recurse
spanHandler(txt.substring(pointLocInSpan), cls);
} }
nextPointIndex++;
// recurse
spanHandler(txt.substring(pointLocInSpan), cls);
} }
} }
} return spanHandler;
return spanHandler; };
};
linestylefilter.getFilterStack = function(lineText, textAndClassFunc, abrowser) linestylefilter.getFilterStack = function(lineText, textAndClassFunc, abrowser)
{
var func = linestylefilter.getURLFilter(lineText, textAndClassFunc);
var hookFilters = hooks.callAll("aceGetFilterStack", {
linestylefilter: linestylefilter,
browser: abrowser
});
_.map(hookFilters ,function(hookFilter)
{ {
func = hookFilter(lineText, func); var func = linestylefilter.getURLFilter(lineText, textAndClassFunc);
});
if (abrowser !== undefined && abrowser.msie) var hookFilters = hooks.callAll("aceGetFilterStack", {
linestylefilter: linestylefilter,
browser: abrowser
});
_.map(hookFilters ,function(hookFilter)
{
func = hookFilter(lineText, func);
});
if (abrowser !== undefined && abrowser.msie)
{
// IE7+ will take an e-mail address like <foo@bar.com> and linkify it to foo@bar.com.
// We then normalize it back to text with no angle brackets. It's weird. So always
// break spans at an "at" sign.
func = linestylefilter.getAtSignSplitterFilter(
lineText, func);
}
return func;
};
// domLineObj is like that returned by domline.createDomLine
linestylefilter.populateDomLine = function(textLine, aline, apool, domLineObj)
{ {
// IE7+ will take an e-mail address like <foo@bar.com> and linkify it to foo@bar.com. // remove final newline from text if any
// We then normalize it back to text with no angle brackets. It's weird. So always var text = textLine;
// break spans at an "at" sign. if (text.slice(-1) == '\n')
func = linestylefilter.getAtSignSplitterFilter( {
lineText, func); text = text.substring(0, text.length - 1);
} }
return func;
};
// domLineObj is like that returned by domline.createDomLine function textAndClassFunc(tokenText, tokenClass)
linestylefilter.populateDomLine = function(textLine, aline, apool, domLineObj) {
{ domLineObj.appendSpan(tokenText, tokenClass);
// remove final newline from text if any }
var text = textLine;
if (text.slice(-1) == '\n')
{
text = text.substring(0, text.length - 1);
}
function textAndClassFunc(tokenText, tokenClass) var func = linestylefilter.getFilterStack(text, textAndClassFunc);
{ func = linestylefilter.getLineStyleFilter(text.length, aline, func, apool);
domLineObj.appendSpan(tokenText, tokenClass); func(text, '');
} };
var func = linestylefilter.getFilterStack(text, textAndClassFunc); exports.linestylefilter = linestylefilter;
func = linestylefilter.getLineStyleFilter(text.length, aline, func, apool);
func(text, '');
};
exports.linestylefilter = linestylefilter; return exports;
});

View file

@ -27,8 +27,9 @@ define([
'ep_etherpad-lite/static/js/rjquery', 'ep_etherpad-lite/static/js/rjquery',
'ep_etherpad-lite/static/js/pluginfw/hooks', 'ep_etherpad-lite/static/js/pluginfw/hooks',
'ep_etherpad-lite/static/js/pad_utils', 'ep_etherpad-lite/static/js/pad_utils',
'ep_etherpad-lite/static/js/broadcast_slider' 'ep_etherpad-lite/static/js/broadcast_slider',
], function($, hooks, padUtilsMod, broadcastSliderMod) { 'ep_etherpad-lite/static/js/broadcast',
], function($, hooks, padUtilsMod, broadcastSliderMod, broadcastMod) {
var exports = {}; var exports = {};
JSON = window.requireKernel('./json2'); JSON = window.requireKernel('./json2');
@ -36,6 +37,11 @@ define([
var createCookie = padUtilsMod.createCookie; var createCookie = padUtilsMod.createCookie;
var readCookie = padUtilsMod.readCookie; var readCookie = padUtilsMod.readCookie;
var randomString = padUtilsMod.randomString; var randomString = padUtilsMod.randomString;
var broadcastRevisionsMod = require('./broadcast_revisions');
var padimpexpMod = require('./pad_impexp');
//initialize export ui
require('./pad_impexp').padimpexp.init();
var token, padId, export_links; var token, padId, export_links;
@ -142,11 +148,11 @@ define([
//load all script that doesn't work without the clientVars //load all script that doesn't work without the clientVars
BroadcastSlider = broadcastSliderMod.loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded); BroadcastSlider = broadcastSliderMod.loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);
require('./broadcast_revisions').loadBroadcastRevisionsJS(); broadcastRevisionsMod.loadBroadcastRevisionsJS();
changesetLoader = require('./broadcast').loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider); changesetLoader = broadcastMod.loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider);
//initialize export ui //initialize export ui
require('./pad_impexp').padimpexp.init(); padimpexpMod.padimpexp.init();
//change export urls when the slider moves //change export urls when the slider moves
BroadcastSlider.onSlider(function(revno) BroadcastSlider.onSlider(function(revno)

View file

@ -406,11 +406,9 @@
[ [
'ep_etherpad-lite/static/js/rjquery', 'ep_etherpad-lite/static/js/rjquery',
'ep_etherpad-lite/static/js/pluginfw/client_plugins', 'ep_etherpad-lite/static/js/pluginfw/client_plugins',
'ep_etherpad-lite/static/js/pluginfw/hooks', 'ep_etherpad-lite/static/js/pluginfw/hooks'
'ep_etherpad-lite/static/js/pad', ], function ($, plugins, hooks) {
'ep_etherpad-lite/static/js/chat', console.log("hooks & plugins modules loaded");
'ep_etherpad-lite/static/js/pad_editbar',
], function ($, plugins, hooks, padMod, chatMod, padEditbarMod) {
window.$ = $; // Expose jQuery #HACK window.$ = $; // Expose jQuery #HACK
window.jQuery = $; window.jQuery = $;
@ -423,20 +421,32 @@
plugins.update(function () { plugins.update(function () {
hooks.plugins = plugins; hooks.plugins = plugins;
console.log("hooks.plugins initialized");
// Call documentReady hook // Call documentReady hook
$(function() { $(function() {
hooks.aCallAll('documentReady'); hooks.aCallAll('documentReady');
}); });
padMod.baseURL = baseURL; requirejs(
padMod.init(); [
}); 'ep_etherpad-lite/static/js/pad',
'ep_etherpad-lite/static/js/chat',
'ep_etherpad-lite/static/js/pad_editbar',
], function (padMod, chatMod, padEditbarMod) {
console.log("pad loaded");
/* TODO: These globals shouldn't exist. */ padMod.baseURL = baseURL;
pad = padMod.pad; padMod.init();
chat = chatMod.chat;
padeditbar = padEditbarMod.padeditbar; /* TODO: These globals shouldn't exist. */
padimpexp = window.requireKernel('ep_etherpad-lite/static/js/pad_impexp').padimpexp; pad = padMod.pad;
chat = chatMod.chat;
padeditbar = padEditbarMod.padeditbar;
padimpexp = window.requireKernel('ep_etherpad-lite/static/js/pad_impexp').padimpexp;
}
);
});
} }
); );
}()); }());