resolve conflict with async test

This commit is contained in:
John McLear 2021-01-29 09:19:54 +00:00
commit a908bbee8e
14 changed files with 229 additions and 1139 deletions

View file

@ -11,24 +11,42 @@
"Sebastian Wallroth",
"Thargon",
"Tim.krieger",
"Wikinaut"
"Wikinaut",
"Zunkelty"
]
},
"admin.page-title": "Admin Dashboard - Etherpad",
"admin_plugins": "Plugins verwalten",
"admin_plugins.available": "Verfügbare Plugins",
"admin_plugins.available_not-found": "Keine Plugins gefunden.",
"admin_plugins.available_fetching": "Wird abgerufen...",
"admin_plugins.available_install.value": "Installieren",
"admin_plugins.available_search.placeholder": "Suche nach Plugins zum Installieren",
"admin_plugins.description": "Beschreibung",
"admin_plugins.installed": "Installierte Plugins",
"admin_plugins.installed_fetching": "Rufe installierte Plugins ab...",
"admin_plugins.installed_nothing": "Du hast bisher noch keine Plugins installiert.",
"admin_plugins.installed_uninstall.value": "Deinstallieren",
"admin_plugins.last-update": "Letze Aktualisierung",
"admin_plugins.name": "Name",
"admin_plugins.page-title": "Plugin Manager - Etherpad",
"admin_plugins.version": "Version",
"admin_plugins_info": "Hilfestellung",
"admin_plugins_info.hooks": "Installierte Hooks",
"admin_plugins_info.hooks_client": "Client-seitige Hooks",
"admin_plugins_info.hooks_server": "Server-seitige Hooks",
"admin_plugins_info.parts": "Installierte Teile",
"admin_plugins_info.plugins": "Installierte Plugins",
"admin_plugins_info.page-title": "Plugin Informationen - Etherpad",
"admin_plugins_info.version": "Etherpad Version",
"admin_plugins_info.version_latest": "Neueste Version",
"admin_plugins_info.version_number": "Versionsnummer",
"admin_settings": "Einstellungen",
"admin_settings.current": "Derzeitige Konfiguration",
"admin_settings.current_example-devel": "Beispielhafte Entwicklungseinstellungs-Templates",
"admin_settings.current_restart.value": "Etherpad neustarten",
"admin_settings.current_save.value": "Einstellungen speichern",
"admin_settings.page-title": "Einstellungen - Etherpad",
"index.newPad": "Neues Pad",
"index.createOpenPad": "oder ein Pad mit folgendem Namen erstellen/öffnen:",
"index.openPad": "Öffne ein vorhandenes Pad mit folgendem Namen:",
@ -78,7 +96,7 @@
"pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.abiword.innerHTML": "Du kannst nur aus reinen Text- oder HTML-Formaten importieren. Für umfangreichere Importfunktionen <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">muss AbiWord oder LibreOffice auf dem Server installiert werden</a>.",
"pad.modals.connected": "Verbunden.",
"pad.modals.reconnecting": "Wiederherstellen der Verbindung …",
"pad.modals.reconnecting": "Dein Pad wird neu verbunden...",
"pad.modals.forcereconnect": "Erneutes Verbinden erzwingen",
"pad.modals.reconnecttimer": "Versuche Neuverbindung in",
"pad.modals.cancel": "Abbrechen",
@ -102,6 +120,7 @@
"pad.modals.deleted.explanation": "Dieses Pad wurde entfernt.",
"pad.modals.rateLimited": "Begrenzte Rate.",
"pad.modals.rateLimited.explanation": "Sie haben zu viele Nachrichten an dieses Pad gesendet, so dass die Verbindung unterbrochen wurde.",
"pad.modals.rejected.explanation": "Der Server hat eine Nachricht abgelehnt, die von deinem Browser gesendet wurde.",
"pad.modals.disconnected": "Ihre Verbindung wurde getrennt.",
"pad.modals.disconnected.explanation": "Die Verbindung zum Server wurde unterbrochen.",
"pad.modals.disconnected.cause": "Möglicherweise ist der Server nicht erreichbar. Bitte benachrichtige den Dienstadministrator, falls dies weiterhin passiert.",

View file

@ -18,6 +18,7 @@
"VezonThunder"
]
},
"admin_plugins.available": "Saatavilla olevat liitännäiset",
"admin_plugins.available_install.value": "Lataa",
"admin_plugins.available_search.placeholder": "Etsi asennettavia laajennuksia",
"admin_plugins.description": "Kuvaus",
@ -92,7 +93,7 @@
"pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Monipuoliset tuontiominaisuudet ovat käytettävissä <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">asentamalla AbiWordin tai LibreOfficen</a>.",
"pad.modals.connected": "Yhdistetty.",
"pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...",
"pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen",
"pad.modals.forcereconnect": "Pakota yhdistämään uudelleen",
"pad.modals.reconnecttimer": "Yritetään yhdistää uudelleen",
"pad.modals.cancel": "Peruuta",

View file

@ -9,6 +9,10 @@
"Upwinxp"
]
},
"admin_plugins.last-update": "Zadnja posodobitev",
"admin_plugins.name": "Ime",
"admin_plugins.version": "Različica",
"admin_settings": "Nastavitve",
"index.newPad": "Nov dokument",
"index.createOpenPad": "ali pa ustvari/odpri dokument z imenom:",
"pad.toolbar.bold.title": "Krepko (Ctrl-B)",
@ -54,7 +58,7 @@
"pad.importExport.exportword": "DOC (zapis Microsoft Word)",
"pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)",
"pad.importExport.exportopen": "ODF (zapis Open Document)",
"pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">program AbiWord</a>.",
"pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le neoblikovano besedilo in zapise HTML. Za naprednejše možnosti uvoza namestite program <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">AbiWord</a>.",
"pad.modals.connected": "Povezano.",
"pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...",
"pad.modals.forcereconnect": "Vsili ponovno povezavo",
@ -64,7 +68,7 @@
"pad.modals.userdup.explanation": "Videti je, da je ta dokument odprt v več kot enem oknu brskalnika na tem računalniku.",
"pad.modals.userdup.advice": "Ponovno vzpostavite povezavo in uporabljajte to okno.",
"pad.modals.unauth": "Nepooblaščen dostop",
"pad.modals.unauth.explanation": "Med pregledovanjem te strani so se dovoljenja za ogled spremenila. Poskusite se ponovno povezati.",
"pad.modals.unauth.explanation": "Med ogledovanjem strani so se dovoljenja za ogled spremenila. Poskusite se znova povezati.",
"pad.modals.looping.explanation": "Zaznane so težave pri komunikaciji s strežnikom za usklajevanje.",
"pad.modals.looping.cause": "Morda ste se povezali preko neustrezno nastavljenega požarnega zidu ali posredniškega strežnika.",
"pad.modals.initsocketfail": "Strežnik je nedosegljiv.",

View file

@ -1217,7 +1217,7 @@ const handleChangesetRequest = async (socket, message) => {
socket.json.send({type: 'CHANGESET_REQ', data});
} catch (err) {
console.error(`Error while handling a changeset request for ${padIds.padId}`,
err.toString(), message.data);
err.toString(), message.data);
}
};

990
src/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -78,18 +78,17 @@
"etherpad-lite": "node/server.js"
},
"devDependencies": {
"eslint": "^7.15.0",
"eslint-config-etherpad": "^1.0.20",
"eslint": "^7.18.0",
"eslint-config-etherpad": "^1.0.24",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-mocha": "^8.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prefer-arrow": "^1.2.2",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
"etherpad-cli-client": "0.0.9",
"mocha": "7.1.2",
"mocha-froth": "^0.2.10",
"nyc": "15.0.1",
"set-cookie-parser": "^2.4.6",
"sinon": "^9.2.0",
"superagent": "^3.8.3",
@ -148,8 +147,8 @@
},
"scripts": {
"lint": "eslint .",
"test": "nyc mocha --timeout 120000 --recursive ../tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs",
"test-container": "nyc mocha --timeout 5000 ../tests/container/specs/api"
"test": "mocha --timeout 120000 --recursive ../tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs",
"test-container": "mocha --timeout 5000 ../tests/container/specs/api"
},
"version": "1.8.7",
"license": "Apache-2.0"

View file

@ -1,3 +1,5 @@
'use strict';
const Changeset = require('./Changeset');
const ChangesetUtils = require('./ChangesetUtils');
const _ = require('./underscore');
@ -72,10 +74,12 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
const rowChangeset = this._setAttributesOnRangeByLine(row, startCol, endCol, attribs);
// compose changesets of all rows into a single changeset, as the range might not be continuous
// compose changesets of all rows into a single changeset
// as the range might not be continuous
// due to the presence of line markers on the rows
if (allChangesets) {
allChangesets = Changeset.compose(allChangesets.toString(), rowChangeset.toString(), this.rep.apool);
allChangesets = Changeset.compose(
allChangesets.toString(), rowChangeset.toString(), this.rep.apool);
} else {
allChangesets = rowChangeset;
}
@ -118,7 +122,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
_setAttributesOnRangeByLine(row, startCol, endCol, attribs) {
const builder = Changeset.builder(this.rep.lines.totalWidth());
ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [row, startCol]);
ChangesetUtils.buildKeepRange(this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
ChangesetUtils.buildKeepRange(
this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
return builder;
},
@ -127,9 +132,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
@param lineNum: the number of the line
*/
lineHasMarker(lineNum) {
const that = this;
return _.find(lineAttributes, (attribute) => that.getAttributeOnLine(lineNum, attribute) != '') !== undefined;
return lineAttributes.find(
(attribute) => this.getAttributeOnLine(lineNum, attribute) !== '') !== undefined;
},
/*
@ -184,7 +188,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
if (!(rep.selStart && rep.selEnd)) return;
// If we're looking for the caret attribute not the selection
// has the user already got a selection or is this purely a caret location?
const isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
const isNotSelection = (rep.selStart[0] === rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
if (isNotSelection) {
if (prevChar) {
// If it's not the start of the line
@ -198,21 +202,18 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
[attributeName, 'true'],
], rep.apool);
const withItRegex = new RegExp(`${withIt.replace(/\*/g, '\\*')}(\\*|$)`);
function hasIt(attribs) {
return withItRegex.test(attribs);
}
const hasIt = (attribs) => withItRegex.test(attribs);
return rangeHasAttrib(rep.selStart, rep.selEnd);
function rangeHasAttrib(selStart, selEnd) {
const rangeHasAttrib = (selStart, selEnd) => {
// if range is collapsed -> no attribs in range
if (selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false;
if (selStart[1] === selEnd[1] && selStart[0] === selEnd[0]) return false;
if (selStart[0] != selEnd[0]) { // -> More than one line selected
var hasAttrib = true;
if (selStart[0] !== selEnd[0]) { // -> More than one line selected
let hasAttrib = true;
// from selStart to the end of the first line
hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]);
hasAttrib = hasAttrib && rangeHasAttrib(
selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]);
// for all lines in between
for (let n = selStart[0] + 1; n < selEnd[0]; n++) {
@ -230,7 +231,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
const lineNum = selStart[0];
const start = selStart[1];
const end = selEnd[1];
var hasAttrib = true;
let hasAttrib = true;
// Iterate over attribs on this line
@ -244,7 +245,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
if (!hasIt(op.attribs)) {
// does op overlap selection?
if (!(opEndInLine <= start || opStartInLine >= end)) {
hasAttrib = false; // since it's overlapping but hasn't got the attrib -> range hasn't got it
// since it's overlapping but hasn't got the attrib -> range hasn't got it
hasAttrib = false;
break;
}
}
@ -252,7 +254,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
}
return hasAttrib;
}
};
return rangeHasAttrib(rep.selStart, rep.selEnd);
},
/*
@ -349,13 +352,13 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
const hasMarker = this.lineHasMarker(lineNum);
let found = false;
const attribs = _(this.getAttributesOnLine(lineNum)).map(function (attrib) {
const attribs = this.getAttributesOnLine(lineNum).map((attrib) => {
if (attrib[0] === attributeName && (!attributeValue || attrib[0] === attributeValue)) {
found = true;
return [attributeName, ''];
return [attrib[0], ''];
} else if (attrib[0] === 'author') {
// update last author to make changes to line attributes on this line
return [attributeName, this.author];
return [attrib[0], this.author];
}
return attrib;
});
@ -373,7 +376,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
if (hasMarker && !countAttribsWithMarker) {
ChangesetUtils.buildRemoveRange(this.rep, builder, [lineNum, 0], [lineNum, 1]);
} else {
ChangesetUtils.buildKeepRange(this.rep, builder, [lineNum, 0], [lineNum, 1], attribs, this.rep.apool);
ChangesetUtils.buildKeepRange(
this.rep, builder, [lineNum, 0], [lineNum, 1], attribs, this.rep.apool);
}
return this.applyChangeset(builder);
@ -394,7 +398,9 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
},
hasAttributeOnSelectionOrCaretPosition(attributeName) {
const hasSelection = ((this.rep.selStart[0] !== this.rep.selEnd[0]) || (this.rep.selEnd[1] !== this.rep.selStart[1]));
const hasSelection = (
(this.rep.selStart[0] !== this.rep.selEnd[0]) || (this.rep.selEnd[1] !== this.rep.selStart[1])
);
let hasAttrib;
if (hasSelection) {
hasAttrib = this.getAttributeOnSelection(attributeName);

View file

@ -1,3 +1,5 @@
'use strict';
/**
* 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.
@ -22,33 +24,23 @@
const Security = require('./security');
function isNodeText(node) {
return (node.nodeType == 3);
}
const isNodeText = (node) => (node.nodeType === 3);
function object(o) {
const f = function () {};
f.prototype = o;
return new f();
}
const getAssoc = (obj, name) => obj[`_magicdom_${name}`];
function getAssoc(obj, name) {
return obj[`_magicdom_${name}`];
}
function setAssoc(obj, name, value) {
const setAssoc = (obj, name, value) => {
// note that in IE designMode, properties of a node can get
// copied to new nodes that are spawned during editing; also,
// properties representable in HTML text can survive copy-and-paste
obj[`_magicdom_${name}`] = value;
}
};
// "func" is a function over 0..(numItems-1) that is monotonically
// "increasing" with index (false, then true). Finds the boundary
// between false and true, a number between 0 and numItems inclusive.
function binarySearch(numItems, func) {
const binarySearch = (numItems, func) => {
if (numItems < 1) return 0;
if (func(0)) return 0;
if (!func(numItems - 1)) return numItems;
@ -60,22 +52,19 @@ function binarySearch(numItems, func) {
else low = x;
}
return high;
}
};
function binarySearchInfinite(expectedLength, func) {
const binarySearchInfinite = (expectedLength, func) => {
let i = 0;
while (!func(i)) i += expectedLength;
return binarySearch(i, func);
}
};
function htmlPrettyEscape(str) {
return Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
}
const htmlPrettyEscape = (str) => Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
const noop = function () {};
const noop = () => {};
exports.isNodeText = isNodeText;
exports.object = object;
exports.getAssoc = getAssoc;
exports.setAssoc = setAssoc;
exports.binarySearch = binarySearch;

View file

@ -113,7 +113,7 @@ const reconnectionTries = {
nextTry() {
// double the time to try to reconnect on every time reconnection fails
const nextCounterFactor = Math.pow(2, this.counter);
const nextCounterFactor = 2 ** this.counter;
this.counter++;
return nextCounterFactor;

View file

@ -55,7 +55,7 @@ const tsort = (edges) => {
Object.keys(nodes).forEach(visit);
return sorted;
}
};
/**
* TEST