mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 14:13:34 +01:00
Share the AttributePoolFactory
, Changeset
, and contentcollector
modules.
This commit is contained in:
parent
3dabe81989
commit
f8f80968ca
16 changed files with 39 additions and 5450 deletions
|
@ -15,7 +15,8 @@ var log4js = require("log4js");
|
||||||
log4js.setGlobalLogLevel("INFO");
|
log4js.setGlobalLogLevel("INFO");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var db = require('../node/db/DB');
|
var db = require('../node/db/DB');
|
||||||
var Changeset = require('../node/utils/Changeset');
|
var CommonCode = require('../node/utils/common_code');
|
||||||
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var padManager;
|
var padManager;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
var CommonCode = require('../node/utils/common_code');
|
||||||
var startTime = new Date().getTime();
|
var startTime = new Date().getTime();
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var ueberDB = require("ueberDB");
|
var ueberDB = require("ueberDB");
|
||||||
var mysql = require("mysql");
|
var mysql = require("mysql");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var Changeset = require("../node/utils/Changeset");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var randomString = require("../node/utils/randomstring");
|
var randomString = require("../node/utils/randomstring");
|
||||||
var AttributePoolFactory = require("../node/utils/AttributePoolFactory");
|
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||||
|
|
||||||
var settingsFile = process.argv[2];
|
var settingsFile = process.argv[2];
|
||||||
var sqlOutputFile = process.argv[3];
|
var sqlOutputFile = process.argv[3];
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
* The pad object, defined with joose
|
* The pad object, defined with joose
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var CommonCode = require('../utils/common_code');
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var Changeset = require("../utils/Changeset");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var AttributePoolFactory = require("../utils/AttributePoolFactory");
|
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||||
var db = require("./DB").db;
|
var db = require("./DB").db;
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var settings = require('../utils/Settings');
|
var settings = require('../utils/Settings');
|
||||||
|
|
|
@ -20,8 +20,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Changeset = require('./utils/Changeset');
|
var CommonCode = require('./utils/common_code');
|
||||||
var AttributePoolFactory = require("./utils/AttributePoolFactory");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
|
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||||
|
|
||||||
function random() {
|
function random() {
|
||||||
this.nextInt = function (maxValue) {
|
this.nextInt = function (maxValue) {
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var CommonCode = require('../utils/common_code');
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var Changeset = require("../utils/Changeset");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var AttributePoolFactory = require("../utils/AttributePoolFactory");
|
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||||
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');
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var CommonCode = require('../utils/common_code');
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var Changeset = require("../utils/Changeset");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var AttributePoolFactory = require("../utils/AttributePoolFactory");
|
var AttributePoolFactory = CommonCode.require("/AttributePoolFactory");
|
||||||
var settings = require('../utils/Settings');
|
var settings = require('../utils/Settings');
|
||||||
var authorManager = require("../db/AuthorManager");
|
var authorManager = require("../db/AuthorManager");
|
||||||
var log4js = require('log4js');
|
var log4js = require('log4js');
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var Changeset = require("./Changeset");
|
var CommonCode = require('./common_code');
|
||||||
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
|
|
||||||
function getPadDokuWiki(pad, revNum, callback)
|
function getPadDokuWiki(pad, revNum, callback)
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var CommonCode = require('./common_code');
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var Changeset = require("./Changeset");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
var jsdom = require('jsdom-nocontextifiy').jsdom;
|
var jsdom = require('jsdom-nocontextifiy').jsdom;
|
||||||
var log4js = require('log4js');
|
var log4js = require('log4js');
|
||||||
|
|
||||||
var Changeset = require("./Changeset");
|
var CommonCode = require('../utils/common_code');
|
||||||
var contentcollector = require("./contentcollector");
|
var Changeset = CommonCode.require("/Changeset");
|
||||||
var map = require("../../static/js/ace2_common.js").map;
|
var contentcollector = CommonCode.require("/contentcollector");
|
||||||
|
var map = CommonCode.require("/ace2_common").map;
|
||||||
|
|
||||||
function setPadHTML(pad, html, callback)
|
function setPadHTML(pad, html, callback)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,692 +0,0 @@
|
||||||
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.contentcollector
|
|
||||||
// %APPJET%: import("etherpad.collab.ace.easysync2.Changeset");
|
|
||||||
// %APPJET%: import("etherpad.admin.plugins");
|
|
||||||
/**
|
|
||||||
* Copyright 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Changeset = require("../utils/Changeset");
|
|
||||||
|
|
||||||
var _MAX_LIST_LEVEL = 8;
|
|
||||||
|
|
||||||
function sanitizeUnicode(s)
|
|
||||||
{
|
|
||||||
return s.replace(/[\uffff\ufffe\ufeff\ufdd0-\ufdef\ud800-\udfff]/g, '?');
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeContentCollector(collectStyles, browser, apool, domInterface, className2Author)
|
|
||||||
{
|
|
||||||
browser = browser || {};
|
|
||||||
|
|
||||||
var plugins_;
|
|
||||||
if (typeof(plugins) != 'undefined')
|
|
||||||
{
|
|
||||||
plugins_ = plugins;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugins_ = {callHook: function () {}};
|
|
||||||
}
|
|
||||||
|
|
||||||
var dom = domInterface || {
|
|
||||||
isNodeText: function(n)
|
|
||||||
{
|
|
||||||
return (n.nodeType == 3);
|
|
||||||
},
|
|
||||||
nodeTagName: function(n)
|
|
||||||
{
|
|
||||||
return n.tagName;
|
|
||||||
},
|
|
||||||
nodeValue: function(n)
|
|
||||||
{
|
|
||||||
return n.nodeValue;
|
|
||||||
},
|
|
||||||
nodeNumChildren: function(n)
|
|
||||||
{
|
|
||||||
return n.childNodes.length;
|
|
||||||
},
|
|
||||||
nodeChild: function(n, i)
|
|
||||||
{
|
|
||||||
return n.childNodes.item(i);
|
|
||||||
},
|
|
||||||
nodeProp: function(n, p)
|
|
||||||
{
|
|
||||||
return n[p];
|
|
||||||
},
|
|
||||||
nodeAttr: function(n, a)
|
|
||||||
{
|
|
||||||
return n.getAttribute(a);
|
|
||||||
},
|
|
||||||
optNodeInnerHTML: function(n)
|
|
||||||
{
|
|
||||||
return n.innerHTML;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _blockElems = {
|
|
||||||
"div": 1,
|
|
||||||
"p": 1,
|
|
||||||
"pre": 1,
|
|
||||||
"li": 1
|
|
||||||
};
|
|
||||||
|
|
||||||
function isBlockElement(n)
|
|
||||||
{
|
|
||||||
return !!_blockElems[(dom.nodeTagName(n) || "").toLowerCase()];
|
|
||||||
}
|
|
||||||
|
|
||||||
function textify(str)
|
|
||||||
{
|
|
||||||
return sanitizeUnicode(
|
|
||||||
str.replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAssoc(node, name)
|
|
||||||
{
|
|
||||||
return dom.nodeProp(node, "_magicdom_" + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = (function()
|
|
||||||
{
|
|
||||||
var textArray = [];
|
|
||||||
var attribsArray = [];
|
|
||||||
var attribsBuilder = null;
|
|
||||||
var op = Changeset.newOp('+');
|
|
||||||
var self = {
|
|
||||||
length: function()
|
|
||||||
{
|
|
||||||
return textArray.length;
|
|
||||||
},
|
|
||||||
atColumnZero: function()
|
|
||||||
{
|
|
||||||
return textArray[textArray.length - 1] === "";
|
|
||||||
},
|
|
||||||
startNew: function()
|
|
||||||
{
|
|
||||||
textArray.push("");
|
|
||||||
self.flush(true);
|
|
||||||
attribsBuilder = Changeset.smartOpAssembler();
|
|
||||||
},
|
|
||||||
textOfLine: function(i)
|
|
||||||
{
|
|
||||||
return textArray[i];
|
|
||||||
},
|
|
||||||
appendText: function(txt, attrString)
|
|
||||||
{
|
|
||||||
textArray[textArray.length - 1] += txt;
|
|
||||||
//dmesg(txt+" / "+attrString);
|
|
||||||
op.attribs = attrString;
|
|
||||||
op.chars = txt.length;
|
|
||||||
attribsBuilder.append(op);
|
|
||||||
},
|
|
||||||
textLines: function()
|
|
||||||
{
|
|
||||||
return textArray.slice();
|
|
||||||
},
|
|
||||||
attribLines: function()
|
|
||||||
{
|
|
||||||
return attribsArray;
|
|
||||||
},
|
|
||||||
// call flush only when you're done
|
|
||||||
flush: function(withNewline)
|
|
||||||
{
|
|
||||||
if (attribsBuilder)
|
|
||||||
{
|
|
||||||
attribsArray.push(attribsBuilder.toString());
|
|
||||||
attribsBuilder = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.startNew();
|
|
||||||
return self;
|
|
||||||
}());
|
|
||||||
var cc = {};
|
|
||||||
|
|
||||||
function _ensureColumnZero(state)
|
|
||||||
{
|
|
||||||
if (!lines.atColumnZero())
|
|
||||||
{
|
|
||||||
cc.startNewLine(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var selection, startPoint, endPoint;
|
|
||||||
var selStart = [-1, -1],
|
|
||||||
selEnd = [-1, -1];
|
|
||||||
var blockElems = {
|
|
||||||
"div": 1,
|
|
||||||
"p": 1,
|
|
||||||
"pre": 1
|
|
||||||
};
|
|
||||||
|
|
||||||
function _isEmpty(node, state)
|
|
||||||
{
|
|
||||||
// consider clean blank lines pasted in IE to be empty
|
|
||||||
if (dom.nodeNumChildren(node) == 0) return true;
|
|
||||||
if (dom.nodeNumChildren(node) == 1 && getAssoc(node, "shouldBeEmpty") && dom.optNodeInnerHTML(node) == " " && !getAssoc(node, "unpasted"))
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
var child = dom.nodeChild(node, 0);
|
|
||||||
_reachPoint(child, 0, state);
|
|
||||||
_reachPoint(child, 1, state);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _pointHere(charsAfter, state)
|
|
||||||
{
|
|
||||||
var ln = lines.length() - 1;
|
|
||||||
var chr = lines.textOfLine(ln).length;
|
|
||||||
if (chr == 0 && state.listType && state.listType != 'none')
|
|
||||||
{
|
|
||||||
chr += 1; // listMarker
|
|
||||||
}
|
|
||||||
chr += charsAfter;
|
|
||||||
return [ln, chr];
|
|
||||||
}
|
|
||||||
|
|
||||||
function _reachBlockPoint(nd, idx, state)
|
|
||||||
{
|
|
||||||
if (!dom.isNodeText(nd)) _reachPoint(nd, idx, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _reachPoint(nd, idx, state)
|
|
||||||
{
|
|
||||||
if (startPoint && nd == startPoint.node && startPoint.index == idx)
|
|
||||||
{
|
|
||||||
selStart = _pointHere(0, state);
|
|
||||||
}
|
|
||||||
if (endPoint && nd == endPoint.node && endPoint.index == idx)
|
|
||||||
{
|
|
||||||
selEnd = _pointHere(0, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cc.incrementFlag = function(state, flagName)
|
|
||||||
{
|
|
||||||
state.flags[flagName] = (state.flags[flagName] || 0) + 1;
|
|
||||||
}
|
|
||||||
cc.decrementFlag = function(state, flagName)
|
|
||||||
{
|
|
||||||
state.flags[flagName]--;
|
|
||||||
}
|
|
||||||
cc.incrementAttrib = function(state, attribName)
|
|
||||||
{
|
|
||||||
if (!state.attribs[attribName])
|
|
||||||
{
|
|
||||||
state.attribs[attribName] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.attribs[attribName]++;
|
|
||||||
}
|
|
||||||
_recalcAttribString(state);
|
|
||||||
}
|
|
||||||
cc.decrementAttrib = function(state, attribName)
|
|
||||||
{
|
|
||||||
state.attribs[attribName]--;
|
|
||||||
_recalcAttribString(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _enterList(state, listType)
|
|
||||||
{
|
|
||||||
var oldListType = state.listType;
|
|
||||||
state.listLevel = (state.listLevel || 0) + 1;
|
|
||||||
if (listType != 'none')
|
|
||||||
{
|
|
||||||
state.listNesting = (state.listNesting || 0) + 1;
|
|
||||||
}
|
|
||||||
state.listType = listType;
|
|
||||||
_recalcAttribString(state);
|
|
||||||
return oldListType;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _exitList(state, oldListType)
|
|
||||||
{
|
|
||||||
state.listLevel--;
|
|
||||||
if (state.listType != 'none')
|
|
||||||
{
|
|
||||||
state.listNesting--;
|
|
||||||
}
|
|
||||||
state.listType = oldListType;
|
|
||||||
_recalcAttribString(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _enterAuthor(state, author)
|
|
||||||
{
|
|
||||||
var oldAuthor = state.author;
|
|
||||||
state.authorLevel = (state.authorLevel || 0) + 1;
|
|
||||||
state.author = author;
|
|
||||||
_recalcAttribString(state);
|
|
||||||
return oldAuthor;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _exitAuthor(state, oldAuthor)
|
|
||||||
{
|
|
||||||
state.authorLevel--;
|
|
||||||
state.author = oldAuthor;
|
|
||||||
_recalcAttribString(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _recalcAttribString(state)
|
|
||||||
{
|
|
||||||
var lst = [];
|
|
||||||
for (var a in state.attribs)
|
|
||||||
{
|
|
||||||
if (state.attribs[a])
|
|
||||||
{
|
|
||||||
lst.push([a, 'true']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (state.authorLevel > 0)
|
|
||||||
{
|
|
||||||
var authorAttrib = ['author', state.author];
|
|
||||||
if (apool.putAttrib(authorAttrib, true) >= 0)
|
|
||||||
{
|
|
||||||
// require that author already be in pool
|
|
||||||
// (don't add authors from other documents, etc.)
|
|
||||||
lst.push(authorAttrib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.attribString = Changeset.makeAttribsString('+', lst, apool);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _produceListMarker(state)
|
|
||||||
{
|
|
||||||
lines.appendText('*', Changeset.makeAttribsString('+', [
|
|
||||||
['list', state.listType],
|
|
||||||
['insertorder', 'first']
|
|
||||||
], apool));
|
|
||||||
}
|
|
||||||
cc.startNewLine = function(state)
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
|
|
||||||
if (atBeginningOfLine && state.listType && state.listType != 'none')
|
|
||||||
{
|
|
||||||
_produceListMarker(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lines.startNew();
|
|
||||||
}
|
|
||||||
cc.notifySelection = function(sel)
|
|
||||||
{
|
|
||||||
if (sel)
|
|
||||||
{
|
|
||||||
selection = sel;
|
|
||||||
startPoint = selection.startPoint;
|
|
||||||
endPoint = selection.endPoint;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cc.doAttrib = function(state, na)
|
|
||||||
{
|
|
||||||
state.localAttribs = (state.localAttribs || []);
|
|
||||||
state.localAttribs.push(na);
|
|
||||||
cc.incrementAttrib(state, na);
|
|
||||||
};
|
|
||||||
cc.collectContent = function(node, state)
|
|
||||||
{
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
state = {
|
|
||||||
flags: { /*name -> nesting counter*/
|
|
||||||
},
|
|
||||||
localAttribs: null,
|
|
||||||
attribs: { /*name -> nesting counter*/
|
|
||||||
},
|
|
||||||
attribString: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var localAttribs = state.localAttribs;
|
|
||||||
state.localAttribs = null;
|
|
||||||
var isBlock = isBlockElement(node);
|
|
||||||
var isEmpty = _isEmpty(node, state);
|
|
||||||
if (isBlock) _ensureColumnZero(state);
|
|
||||||
var startLine = lines.length() - 1;
|
|
||||||
_reachBlockPoint(node, 0, state);
|
|
||||||
if (dom.isNodeText(node))
|
|
||||||
{
|
|
||||||
var txt = dom.nodeValue(node);
|
|
||||||
var rest = '';
|
|
||||||
var x = 0; // offset into original text
|
|
||||||
if (txt.length == 0)
|
|
||||||
{
|
|
||||||
if (startPoint && node == startPoint.node)
|
|
||||||
{
|
|
||||||
selStart = _pointHere(0, state);
|
|
||||||
}
|
|
||||||
if (endPoint && node == endPoint.node)
|
|
||||||
{
|
|
||||||
selEnd = _pointHere(0, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (txt.length > 0)
|
|
||||||
{
|
|
||||||
var consumed = 0;
|
|
||||||
if (state.flags.preMode)
|
|
||||||
{
|
|
||||||
var firstLine = txt.split('\n', 1)[0];
|
|
||||||
consumed = firstLine.length + 1;
|
|
||||||
rest = txt.substring(consumed);
|
|
||||||
txt = firstLine;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* will only run this loop body once */
|
|
||||||
}
|
|
||||||
if (startPoint && node == startPoint.node && startPoint.index - x <= txt.length)
|
|
||||||
{
|
|
||||||
selStart = _pointHere(startPoint.index - x, state);
|
|
||||||
}
|
|
||||||
if (endPoint && node == endPoint.node && endPoint.index - x <= txt.length)
|
|
||||||
{
|
|
||||||
selEnd = _pointHere(endPoint.index - x, state);
|
|
||||||
}
|
|
||||||
var txt2 = txt;
|
|
||||||
if ((!state.flags.preMode) && /^[\r\n]*$/.exec(txt))
|
|
||||||
{
|
|
||||||
// prevents textnodes containing just "\n" from being significant
|
|
||||||
// in safari when pasting text, now that we convert them to
|
|
||||||
// spaces instead of removing them, because in other cases
|
|
||||||
// removing "\n" from pasted HTML will collapse words together.
|
|
||||||
txt2 = "";
|
|
||||||
}
|
|
||||||
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
|
|
||||||
if (atBeginningOfLine)
|
|
||||||
{
|
|
||||||
// newlines in the source mustn't become spaces at beginning of line box
|
|
||||||
txt2 = txt2.replace(/^\n*/, '');
|
|
||||||
}
|
|
||||||
if (atBeginningOfLine && state.listType && state.listType != 'none')
|
|
||||||
{
|
|
||||||
_produceListMarker(state);
|
|
||||||
}
|
|
||||||
lines.appendText(textify(txt2), state.attribString);
|
|
||||||
x += consumed;
|
|
||||||
txt = rest;
|
|
||||||
if (txt.length > 0)
|
|
||||||
{
|
|
||||||
cc.startNewLine(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var tname = (dom.nodeTagName(node) || "").toLowerCase();
|
|
||||||
if (tname == "br")
|
|
||||||
{
|
|
||||||
cc.startNewLine(state);
|
|
||||||
}
|
|
||||||
else if (tname == "script" || tname == "style")
|
|
||||||
{
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
else if (!isEmpty)
|
|
||||||
{
|
|
||||||
var styl = dom.nodeAttr(node, "style");
|
|
||||||
var cls = dom.nodeProp(node, "className");
|
|
||||||
|
|
||||||
var isPre = (tname == "pre");
|
|
||||||
if ((!isPre) && browser.safari)
|
|
||||||
{
|
|
||||||
isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl));
|
|
||||||
}
|
|
||||||
if (isPre) cc.incrementFlag(state, 'preMode');
|
|
||||||
var oldListTypeOrNull = null;
|
|
||||||
var oldAuthorOrNull = null;
|
|
||||||
if (collectStyles)
|
|
||||||
{
|
|
||||||
plugins_.callHook('collectContentPre', {
|
|
||||||
cc: cc,
|
|
||||||
state: state,
|
|
||||||
tname: tname,
|
|
||||||
styl: styl,
|
|
||||||
cls: cls
|
|
||||||
});
|
|
||||||
if (tname == "b" || (styl && /\bfont-weight:\s*bold\b/i.exec(styl)) || tname == "strong")
|
|
||||||
{
|
|
||||||
cc.doAttrib(state, "bold");
|
|
||||||
}
|
|
||||||
if (tname == "i" || (styl && /\bfont-style:\s*italic\b/i.exec(styl)) || tname == "em")
|
|
||||||
{
|
|
||||||
cc.doAttrib(state, "italic");
|
|
||||||
}
|
|
||||||
if (tname == "u" || (styl && /\btext-decoration:\s*underline\b/i.exec(styl)) || tname == "ins")
|
|
||||||
{
|
|
||||||
cc.doAttrib(state, "underline");
|
|
||||||
}
|
|
||||||
if (tname == "s" || (styl && /\btext-decoration:\s*line-through\b/i.exec(styl)) || tname == "del")
|
|
||||||
{
|
|
||||||
cc.doAttrib(state, "strikethrough");
|
|
||||||
}
|
|
||||||
if (tname == "ul" || tname == "ol")
|
|
||||||
{
|
|
||||||
var type;
|
|
||||||
var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls);
|
|
||||||
type = rr && rr[1] || "bullet" + 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');
|
|
||||||
}
|
|
||||||
if (className2Author && cls)
|
|
||||||
{
|
|
||||||
var classes = cls.match(/\S+/g);
|
|
||||||
if (classes && classes.length > 0)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < classes.length; i++)
|
|
||||||
{
|
|
||||||
var c = classes[i];
|
|
||||||
var a = className2Author(c);
|
|
||||||
if (a)
|
|
||||||
{
|
|
||||||
oldAuthorOrNull = (_enterAuthor(state, a) || 'none');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nc = dom.nodeNumChildren(node);
|
|
||||||
for (var i = 0; i < nc; i++)
|
|
||||||
{
|
|
||||||
var c = dom.nodeChild(node, i);
|
|
||||||
cc.collectContent(c, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collectStyles)
|
|
||||||
{
|
|
||||||
plugins_.callHook('collectContentPost', {
|
|
||||||
cc: cc,
|
|
||||||
state: state,
|
|
||||||
tname: tname,
|
|
||||||
styl: styl,
|
|
||||||
cls: cls
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPre) cc.decrementFlag(state, 'preMode');
|
|
||||||
if (state.localAttribs)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < state.localAttribs.length; i++)
|
|
||||||
{
|
|
||||||
cc.decrementAttrib(state, state.localAttribs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldListTypeOrNull)
|
|
||||||
{
|
|
||||||
_exitList(state, oldListTypeOrNull);
|
|
||||||
}
|
|
||||||
if (oldAuthorOrNull)
|
|
||||||
{
|
|
||||||
_exitAuthor(state, oldAuthorOrNull);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!browser.msie)
|
|
||||||
{
|
|
||||||
_reachBlockPoint(node, 1, state);
|
|
||||||
}
|
|
||||||
if (isBlock)
|
|
||||||
{
|
|
||||||
if (lines.length() - 1 == startLine)
|
|
||||||
{
|
|
||||||
cc.startNewLine(state);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_ensureColumnZero(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (browser.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
|
|
||||||
cc.notifyNextNode = function(node)
|
|
||||||
{
|
|
||||||
// an "empty block" won't end a line; this addresses an issue in IE with
|
|
||||||
// typing into a blank line at the end of the document. typed text
|
|
||||||
// goes into the body, and the empty line div still looks clean.
|
|
||||||
// it is incorporated as dirty by the rule that a dirty region has
|
|
||||||
// to end a line.
|
|
||||||
if ((!node) || (isBlockElement(node) && !_isEmpty(node)))
|
|
||||||
{
|
|
||||||
_ensureColumnZero(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// each returns [line, char] or [-1,-1]
|
|
||||||
var getSelectionStart = function()
|
|
||||||
{
|
|
||||||
return selStart;
|
|
||||||
};
|
|
||||||
var getSelectionEnd = function()
|
|
||||||
{
|
|
||||||
return selEnd;
|
|
||||||
};
|
|
||||||
|
|
||||||
// returns array of strings for lines found, last entry will be "" if
|
|
||||||
// last line is complete (i.e. if a following span should be on a new line).
|
|
||||||
// can be called at any point
|
|
||||||
cc.getLines = function()
|
|
||||||
{
|
|
||||||
return lines.textLines();
|
|
||||||
};
|
|
||||||
|
|
||||||
cc.finish = function()
|
|
||||||
{
|
|
||||||
lines.flush();
|
|
||||||
var lineAttribs = lines.attribLines();
|
|
||||||
var lineStrings = cc.getLines();
|
|
||||||
|
|
||||||
lineStrings.length--;
|
|
||||||
lineAttribs.length--;
|
|
||||||
|
|
||||||
var ss = getSelectionStart();
|
|
||||||
var se = getSelectionEnd();
|
|
||||||
|
|
||||||
function fixLongLines()
|
|
||||||
{
|
|
||||||
// design mode does not deal with with really long lines!
|
|
||||||
var lineLimit = 2000; // chars
|
|
||||||
var buffer = 10; // chars allowed over before wrapping
|
|
||||||
var linesWrapped = 0;
|
|
||||||
var numLinesAfter = 0;
|
|
||||||
for (var i = lineStrings.length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var oldString = lineStrings[i];
|
|
||||||
var oldAttribString = lineAttribs[i];
|
|
||||||
if (oldString.length > lineLimit + buffer)
|
|
||||||
{
|
|
||||||
var newStrings = [];
|
|
||||||
var newAttribStrings = [];
|
|
||||||
while (oldString.length > lineLimit)
|
|
||||||
{
|
|
||||||
//var semiloc = oldString.lastIndexOf(';', lineLimit-1);
|
|
||||||
//var lengthToTake = (semiloc >= 0 ? (semiloc+1) : lineLimit);
|
|
||||||
lengthToTake = lineLimit;
|
|
||||||
newStrings.push(oldString.substring(0, lengthToTake));
|
|
||||||
oldString = oldString.substring(lengthToTake);
|
|
||||||
newAttribStrings.push(Changeset.subattribution(oldAttribString, 0, lengthToTake));
|
|
||||||
oldAttribString = Changeset.subattribution(oldAttribString, lengthToTake);
|
|
||||||
}
|
|
||||||
if (oldString.length > 0)
|
|
||||||
{
|
|
||||||
newStrings.push(oldString);
|
|
||||||
newAttribStrings.push(oldAttribString);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fixLineNumber(lineChar)
|
|
||||||
{
|
|
||||||
if (lineChar[0] < 0) return;
|
|
||||||
var n = lineChar[0];
|
|
||||||
var c = lineChar[1];
|
|
||||||
if (n > i)
|
|
||||||
{
|
|
||||||
n += (newStrings.length - 1);
|
|
||||||
}
|
|
||||||
else if (n == i)
|
|
||||||
{
|
|
||||||
var a = 0;
|
|
||||||
while (c > newStrings[a].length)
|
|
||||||
{
|
|
||||||
c -= newStrings[a].length;
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
n += a;
|
|
||||||
}
|
|
||||||
lineChar[0] = n;
|
|
||||||
lineChar[1] = c;
|
|
||||||
}
|
|
||||||
fixLineNumber(ss);
|
|
||||||
fixLineNumber(se);
|
|
||||||
linesWrapped++;
|
|
||||||
numLinesAfter += newStrings.length;
|
|
||||||
|
|
||||||
newStrings.unshift(i, 1);
|
|
||||||
lineStrings.splice.apply(lineStrings, newStrings);
|
|
||||||
newAttribStrings.unshift(i, 1);
|
|
||||||
lineAttribs.splice.apply(lineAttribs, newAttribStrings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
linesWrapped: linesWrapped,
|
|
||||||
numLinesAfter: numLinesAfter
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var wrapData = fixLongLines();
|
|
||||||
|
|
||||||
return {
|
|
||||||
selStart: ss,
|
|
||||||
selEnd: se,
|
|
||||||
linesWrapped: wrapData.linesWrapped,
|
|
||||||
numLinesAfter: wrapData.numLinesAfter,
|
|
||||||
lines: lineStrings,
|
|
||||||
lineAttribs: lineAttribs
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.makeContentCollector = makeContentCollector;
|
|
|
@ -39,6 +39,8 @@
|
||||||
, "pad_modals.js"
|
, "pad_modals.js"
|
||||||
, "pad_savedrevs.js"
|
, "pad_savedrevs.js"
|
||||||
, "pad_impexp.js"
|
, "pad_impexp.js"
|
||||||
|
, "AttributePoolFactory.js"
|
||||||
|
, "Changeset.js"
|
||||||
, "easysync2_client.js"
|
, "easysync2_client.js"
|
||||||
, "domline_client.js"
|
, "domline_client.js"
|
||||||
, "linestylefilter_client.js"
|
, "linestylefilter_client.js"
|
||||||
|
@ -50,6 +52,8 @@
|
||||||
]
|
]
|
||||||
, "ace2_inner.js": [
|
, "ace2_inner.js": [
|
||||||
"ace2_common.js"
|
"ace2_common.js"
|
||||||
|
, "AttributePoolFactory.js"
|
||||||
|
, "Changeset.js"
|
||||||
, "skiplist.js"
|
, "skiplist.js"
|
||||||
, "virtual_lines.js"
|
, "virtual_lines.js"
|
||||||
, "easysync2.js"
|
, "easysync2.js"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* This code represents the Attribute Pool Object of the original Etherpad.
|
* This code represents the Attribute Pool Object of the original Etherpad.
|
||||||
* 90% of the code is still like in the original Etherpad
|
* 90% of the code is still like in the original Etherpad
|
||||||
* Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
|
* Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
|
||||||
* You can find a explanation what a attribute pool is here:
|
* You can find a explanation what a attribute pool is here:
|
||||||
* https://github.com/Pita/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt
|
* https://github.com/Pita/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* This is the Changeset library copied from the old Etherpad with some modifications to use it in node.js
|
* This is the Changeset library copied from the old Etherpad with some modifications to use it in node.js
|
||||||
* Can be found in https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
|
* Can be found in https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var AttributePoolFactory = require("./AttributePoolFactory");
|
var AttributePoolFactory = require("/AttributePoolFactory");
|
||||||
|
|
||||||
var _opt = null;
|
var _opt = null;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
var _MAX_LIST_LEVEL = 8;
|
var _MAX_LIST_LEVEL = 8;
|
||||||
|
|
||||||
var Changeset = require('/easysync2').Changeset
|
var Changeset = require('/easysync2').Changeset;
|
||||||
var plugins = require('/plugins').plugins;
|
var plugins = require('/plugins').plugins;
|
||||||
|
|
||||||
function sanitizeUnicode(s)
|
function sanitizeUnicode(s)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue