mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-24 09:26:14 -04:00
Merge pull request #614 from fourplusone/ace2_refactoring
Adding more hooks + some code refactoring
This commit is contained in:
commit
18038ddd50
9 changed files with 112 additions and 34 deletions
|
@ -24,6 +24,7 @@ var async = require("async");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||||
var AttributePool = require("ep_etherpad-lite/static/js/AttributePool");
|
var AttributePool = require("ep_etherpad-lite/static/js/AttributePool");
|
||||||
|
var AttributeManager = require("ep_etherpad-lite/static/js/AttributeManager");
|
||||||
var authorManager = require("../db/AuthorManager");
|
var authorManager = require("../db/AuthorManager");
|
||||||
var readOnlyManager = require("../db/ReadOnlyManager");
|
var readOnlyManager = require("../db/ReadOnlyManager");
|
||||||
var settings = require('../utils/Settings');
|
var settings = require('../utils/Settings');
|
||||||
|
@ -31,6 +32,7 @@ var securityManager = require("../db/SecurityManager");
|
||||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
|
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
|
||||||
var log4js = require('log4js');
|
var log4js = require('log4js');
|
||||||
var messageLogger = log4js.getLogger("message");
|
var messageLogger = log4js.getLogger("message");
|
||||||
|
var _ = require('underscore');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A associative array that translates a session to a pad
|
* A associative array that translates a session to a pad
|
||||||
|
@ -591,8 +593,12 @@ function _correctMarkersInPad(atext, apool) {
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
var op = iter.next();
|
var op = iter.next();
|
||||||
var listValue = Changeset.opAttributeValue(op, 'list', apool);
|
|
||||||
if (listValue) {
|
var hasMarker = _.find(AttributeManager.lineAttributes, function(attribute){
|
||||||
|
return Changeset.opAttributeValue(op, attribute, apool);
|
||||||
|
}) !== undefined;
|
||||||
|
|
||||||
|
if (hasMarker) {
|
||||||
for(var i=0;i<op.chars;i++) {
|
for(var i=0;i<op.chars;i++) {
|
||||||
if (offset > 0 && text.charAt(offset-1) != '\n') {
|
if (offset > 0 && text.charAt(offset-1) != '\n') {
|
||||||
badMarkers.push(offset);
|
badMarkers.push(offset);
|
||||||
|
|
|
@ -17,6 +17,12 @@ var lineAttributes = [lineMarkerAttribute,'list'];
|
||||||
@param rep the document representation to be used
|
@param rep the document representation to be used
|
||||||
@param applyChangesetCallback this callback will be called
|
@param applyChangesetCallback this callback will be called
|
||||||
once a changeset has been built.
|
once a changeset has been built.
|
||||||
|
|
||||||
|
|
||||||
|
A document representation contains
|
||||||
|
- an array `alines` containing 1 attributes string for each line
|
||||||
|
- an Attribute pool `apool`
|
||||||
|
- a SkipList `lines` containing the text lines of the document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var AttributeManager = function(rep, applyChangesetCallback)
|
var AttributeManager = function(rep, applyChangesetCallback)
|
||||||
|
@ -29,6 +35,8 @@ var AttributeManager = function(rep, applyChangesetCallback)
|
||||||
// it will be considered as a line marker
|
// it will be considered as a line marker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AttributeManager.lineAttributes = lineAttributes;
|
||||||
|
|
||||||
AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
|
|
||||||
applyChangeset: function(changeset){
|
applyChangeset: function(changeset){
|
||||||
|
|
|
@ -256,6 +256,10 @@ require.setGlobalKeyPath("require");\n\
|
||||||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||||
$$INCLUDE_CSS("../static/css/pad.css");
|
$$INCLUDE_CSS("../static/css/pad.css");
|
||||||
$$INCLUDE_CSS("../static/custom/pad.css");
|
$$INCLUDE_CSS("../static/custom/pad.css");
|
||||||
|
|
||||||
|
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
||||||
|
includedCSS = includedCSS.concat(additionalCSS);
|
||||||
|
|
||||||
pushStyleTagsFor(iframeHTML, includedCSS);
|
pushStyleTagsFor(iframeHTML, includedCSS);
|
||||||
|
|
||||||
var includedJS = [];
|
var includedJS = [];
|
||||||
|
@ -294,6 +298,11 @@ require.setGlobalKeyPath("require");\n\
|
||||||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||||
$$INCLUDE_CSS("../static/css/pad.css");
|
$$INCLUDE_CSS("../static/css/pad.css");
|
||||||
$$INCLUDE_CSS("../static/custom/pad.css");
|
$$INCLUDE_CSS("../static/custom/pad.css");
|
||||||
|
|
||||||
|
|
||||||
|
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
||||||
|
includedCSS = includedCSS.concat(additionalCSS);
|
||||||
|
|
||||||
pushStyleTagsFor(outerHTML, includedCSS);
|
pushStyleTagsFor(outerHTML, includedCSS);
|
||||||
|
|
||||||
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
||||||
|
|
|
@ -2875,7 +2875,7 @@ function Ace2Inner(){
|
||||||
|
|
||||||
_.each(hooks.callAll('aceRegisterBlockElements'), function(element){
|
_.each(hooks.callAll('aceRegisterBlockElements'), function(element){
|
||||||
_blockElems[element] = 1;
|
_blockElems[element] = 1;
|
||||||
})
|
});
|
||||||
|
|
||||||
function isBlockElement(n)
|
function isBlockElement(n)
|
||||||
{
|
{
|
||||||
|
@ -3365,6 +3365,9 @@ function Ace2Inner(){
|
||||||
var thisLineListType = getLineListType(theLine);
|
var thisLineListType = getLineListType(theLine);
|
||||||
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
|
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
|
||||||
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
|
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
|
||||||
|
|
||||||
|
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
|
||||||
|
|
||||||
if (thisLineListType)
|
if (thisLineListType)
|
||||||
{
|
{
|
||||||
// this line is a list
|
// this line is a list
|
||||||
|
@ -3378,6 +3381,9 @@ function Ace2Inner(){
|
||||||
// delistify
|
// delistify
|
||||||
performDocumentReplaceRange([theLine, 0], [theLine, lineEntry.lineMarker], '');
|
performDocumentReplaceRange([theLine, 0], [theLine, lineEntry.lineMarker], '');
|
||||||
}
|
}
|
||||||
|
}else if (thisLineHasMarker && prevLineEntry){
|
||||||
|
// If the line has any attributes assigned, remove them by removing the marker '*'
|
||||||
|
performDocumentReplaceRange([theLine -1 , prevLineEntry.text.length], [theLine, lineEntry.lineMarker], '');
|
||||||
}
|
}
|
||||||
else if (theLine > 0)
|
else if (theLine > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@ var _MAX_LIST_LEVEL = 8;
|
||||||
|
|
||||||
var Changeset = require('./Changeset');
|
var Changeset = require('./Changeset');
|
||||||
var hooks = require('./pluginfw/hooks');
|
var hooks = require('./pluginfw/hooks');
|
||||||
|
var _ = require('./underscore');
|
||||||
|
|
||||||
function sanitizeUnicode(s)
|
function sanitizeUnicode(s)
|
||||||
{
|
{
|
||||||
|
@ -161,12 +162,6 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
var selection, startPoint, endPoint;
|
var selection, startPoint, endPoint;
|
||||||
var selStart = [-1, -1],
|
var selStart = [-1, -1],
|
||||||
selEnd = [-1, -1];
|
selEnd = [-1, -1];
|
||||||
var blockElems = {
|
|
||||||
"div": 1,
|
|
||||||
"p": 1,
|
|
||||||
"pre": 1
|
|
||||||
};
|
|
||||||
|
|
||||||
function _isEmpty(node, state)
|
function _isEmpty(node, state)
|
||||||
{
|
{
|
||||||
// consider clean blank lines pasted in IE to be empty
|
// consider clean blank lines pasted in IE to be empty
|
||||||
|
@ -188,7 +183,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
{
|
{
|
||||||
var ln = lines.length() - 1;
|
var ln = lines.length() - 1;
|
||||||
var chr = lines.textOfLine(ln).length;
|
var chr = lines.textOfLine(ln).length;
|
||||||
if (chr == 0 && state.listType && state.listType != 'none')
|
if (chr == 0 && !_.isEmpty(state.lineAttributes))
|
||||||
{
|
{
|
||||||
chr += 1; // listMarker
|
chr += 1; // listMarker
|
||||||
}
|
}
|
||||||
|
@ -240,25 +235,30 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
|
|
||||||
function _enterList(state, listType)
|
function _enterList(state, listType)
|
||||||
{
|
{
|
||||||
var oldListType = state.listType;
|
var oldListType = state.lineAttributes['list'];
|
||||||
state.listLevel = (state.listLevel || 0) + 1;
|
|
||||||
if (listType != 'none')
|
if (listType != 'none')
|
||||||
{
|
{
|
||||||
state.listNesting = (state.listNesting || 0) + 1;
|
state.listNesting = (state.listNesting || 0) + 1;
|
||||||
}
|
}
|
||||||
state.listType = listType;
|
|
||||||
|
if(listType === 'none' || !listType ){
|
||||||
|
delete state.lineAttributes['list'];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
state.lineAttributes['list'] = listType;
|
||||||
|
}
|
||||||
|
|
||||||
_recalcAttribString(state);
|
_recalcAttribString(state);
|
||||||
return oldListType;
|
return oldListType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _exitList(state, oldListType)
|
function _exitList(state, oldListType)
|
||||||
{
|
{
|
||||||
state.listLevel--;
|
if (state.lineAttributes['list'])
|
||||||
if (state.listType != 'none')
|
|
||||||
{
|
{
|
||||||
state.listNesting--;
|
state.listNesting--;
|
||||||
}
|
}
|
||||||
state.listType = oldListType;
|
if(oldListType) state.lineAttributes['list'] = oldListType;
|
||||||
_recalcAttribString(state);
|
_recalcAttribString(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,21 +301,29 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
state.attribString = Changeset.makeAttribsString('+', lst, apool);
|
state.attribString = Changeset.makeAttribsString('+', lst, apool);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _produceListMarker(state)
|
function _produceLineAttributesMarker(state)
|
||||||
{
|
{
|
||||||
lines.appendText('*', Changeset.makeAttribsString('+', [
|
// TODO: This has to go to AttributeManager.
|
||||||
['list', state.listType],
|
var attributes = [
|
||||||
|
['lmkr', '1'],
|
||||||
['insertorder', 'first']
|
['insertorder', 'first']
|
||||||
], apool));
|
].concat(
|
||||||
|
_.map(state.lineAttributes,function(value,key){
|
||||||
|
console.log([key, value])
|
||||||
|
return [key, value];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
|
||||||
}
|
}
|
||||||
cc.startNewLine = function(state)
|
cc.startNewLine = function(state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
|
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
|
||||||
if (atBeginningOfLine && state.listType && state.listType != 'none')
|
if (atBeginningOfLine && !_.isEmpty(state.lineAttributes))
|
||||||
{
|
{
|
||||||
_produceListMarker(state);
|
_produceLineAttributesMarker(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines.startNew();
|
lines.startNew();
|
||||||
|
@ -345,7 +353,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
localAttribs: null,
|
localAttribs: null,
|
||||||
attribs: { /*name -> nesting counter*/
|
attribs: { /*name -> nesting counter*/
|
||||||
},
|
},
|
||||||
attribString: ''
|
attribString: '',
|
||||||
|
// lineAttributes maintain a map from attributes to attribute values set on a line
|
||||||
|
lineAttributes: {
|
||||||
|
/*
|
||||||
|
example:
|
||||||
|
'list': 'bullet1',
|
||||||
|
*/
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var localAttribs = state.localAttribs;
|
var localAttribs = state.localAttribs;
|
||||||
|
@ -407,9 +422,9 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
// newlines in the source mustn't become spaces at beginning of line box
|
// newlines in the source mustn't become spaces at beginning of line box
|
||||||
txt2 = txt2.replace(/^\n*/, '');
|
txt2 = txt2.replace(/^\n*/, '');
|
||||||
}
|
}
|
||||||
if (atBeginningOfLine && state.listType && state.listType != 'none')
|
if (atBeginningOfLine && !_.isEmpty(state.lineAttributes))
|
||||||
{
|
{
|
||||||
_produceListMarker(state);
|
_produceLineAttributesMarker(state);
|
||||||
}
|
}
|
||||||
lines.appendText(textify(txt2), state.attribString);
|
lines.appendText(textify(txt2), state.attribString);
|
||||||
x += consumed;
|
x += consumed;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
var Security = require('./security');
|
var Security = require('./security');
|
||||||
var hooks = require('./pluginfw/hooks');
|
var hooks = require('./pluginfw/hooks');
|
||||||
var _ = require('./underscore');
|
var _ = require('./underscore');
|
||||||
|
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
|
||||||
var Ace2Common = require('./ace2_common');
|
var Ace2Common = require('./ace2_common');
|
||||||
var noop = Ace2Common.noop;
|
var noop = Ace2Common.noop;
|
||||||
|
|
||||||
|
@ -82,7 +82,8 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
var preHtml, postHtml;
|
var preHtml = '',
|
||||||
|
postHtml = '';
|
||||||
var curHTML = null;
|
var curHTML = null;
|
||||||
|
|
||||||
function processSpaces(s)
|
function processSpaces(s)
|
||||||
|
@ -95,7 +96,9 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
var lineClass = 'ace-line';
|
var lineClass = 'ace-line';
|
||||||
result.appendSpan = function(txt, cls)
|
result.appendSpan = function(txt, cls)
|
||||||
{
|
{
|
||||||
if (cls.indexOf('list') >= 0)
|
var processedMarker = false;
|
||||||
|
// Handle lineAttributeMarker, if present
|
||||||
|
if (cls.indexOf(lineAttributeMarker) >= 0)
|
||||||
{
|
{
|
||||||
var listType = /(?:^| )list:(\S+)/.exec(cls);
|
var listType = /(?:^| )list:(\S+)/.exec(cls);
|
||||||
var start = /(?:^| )start:(\S+)/.exec(cls);
|
var start = /(?:^| )start:(\S+)/.exec(cls);
|
||||||
|
@ -116,9 +119,25 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
postHtml = '</li></ol>';
|
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;
|
result.lineMarker += txt.length;
|
||||||
return; // don't append any text
|
return; // don't append any text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
var href = null;
|
var href = null;
|
||||||
var simpleTags = null;
|
var simpleTags = null;
|
||||||
|
@ -203,7 +222,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
{
|
{
|
||||||
newHTML = (preHtml || '') + newHTML + (postHtml || '');
|
newHTML = (preHtml || '') + newHTML + (postHtml || '');
|
||||||
}
|
}
|
||||||
html = preHtml = postHtml = null; // free memory
|
html = preHtml = postHtml = ''; // free memory
|
||||||
if (newHTML !== curHTML)
|
if (newHTML !== curHTML)
|
||||||
{
|
{
|
||||||
curHTML = newHTML;
|
curHTML = newHTML;
|
||||||
|
|
|
@ -32,6 +32,8 @@ var Changeset = require('./Changeset');
|
||||||
var hooks = require('./pluginfw/hooks');
|
var hooks = require('./pluginfw/hooks');
|
||||||
var linestylefilter = {};
|
var linestylefilter = {};
|
||||||
var _ = require('./underscore');
|
var _ = require('./underscore');
|
||||||
|
var AttributeManager = require('./AttributeManager');
|
||||||
|
|
||||||
|
|
||||||
linestylefilter.ATTRIB_CLASSES = {
|
linestylefilter.ATTRIB_CLASSES = {
|
||||||
'bold': 'tag:b',
|
'bold': 'tag:b',
|
||||||
|
@ -40,6 +42,9 @@ linestylefilter.ATTRIB_CLASSES = {
|
||||||
'strikethrough': 'tag:s'
|
'strikethrough': 'tag:s'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var lineAttributeMarker = 'lineAttribMarker';
|
||||||
|
exports.lineAttributeMarker = lineAttributeMarker;
|
||||||
|
|
||||||
linestylefilter.getAuthorClassName = function(author)
|
linestylefilter.getAuthorClassName = function(author)
|
||||||
{
|
{
|
||||||
return "author-" + author.replace(/[^a-y0-9]/g, function(c)
|
return "author-" + author.replace(/[^a-y0-9]/g, function(c)
|
||||||
|
@ -68,6 +73,8 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
function attribsToClasses(attribs)
|
function attribsToClasses(attribs)
|
||||||
{
|
{
|
||||||
var classes = '';
|
var classes = '';
|
||||||
|
var isLineAttribMarker = false;
|
||||||
|
|
||||||
Changeset.eachAttribNumber(attribs, function(n)
|
Changeset.eachAttribNumber(attribs, function(n)
|
||||||
{
|
{
|
||||||
var key = apool.getAttribKey(n);
|
var key = apool.getAttribKey(n);
|
||||||
|
@ -76,6 +83,9 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
var value = apool.getAttribValue(n);
|
var value = apool.getAttribValue(n);
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
|
if (!isLineAttribMarker && _.indexOf(AttributeManager.lineAttributes, key) >= 0){
|
||||||
|
isLineAttribMarker = true;
|
||||||
|
}
|
||||||
if (key == 'author')
|
if (key == 'author')
|
||||||
{
|
{
|
||||||
classes += ' ' + linestylefilter.getAuthorClassName(value);
|
classes += ' ' + linestylefilter.getAuthorClassName(value);
|
||||||
|
@ -103,6 +113,8 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
|
||||||
return classes.substring(1);
|
return classes.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -534,7 +534,7 @@ var pad = {
|
||||||
if(padcookie.getPref("showAuthorshipColors") == false){
|
if(padcookie.getPref("showAuthorshipColors") == false){
|
||||||
pad.changeViewOption('showAuthorColors', false);
|
pad.changeViewOption('showAuthorColors', false);
|
||||||
}
|
}
|
||||||
hooks.aCallAll("postAceInit");
|
hooks.aCallAll("postAceInit", {ace: padeditor.ace});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dispose: function()
|
dispose: function()
|
||||||
|
|
|
@ -155,6 +155,9 @@ function SkipList()
|
||||||
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
|
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
|
||||||
var newWidth = _entryWidth(entry);
|
var newWidth = _entryWidth(entry);
|
||||||
p.mark("loop1");
|
p.mark("loop1");
|
||||||
|
|
||||||
|
// The new node will have at least level 1
|
||||||
|
// With a proability of 0.01^(n-1) the nodes level will be >= n
|
||||||
while (newNode.levels == 0 || Math.random() < 0.01)
|
while (newNode.levels == 0 || Math.random() < 0.01)
|
||||||
{
|
{
|
||||||
var lvl = newNode.levels;
|
var lvl = newNode.levels;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue