Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging

pull/1/head
yflory 4 years ago
commit 0359ce32de

@ -62,7 +62,7 @@ define([
var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ?
'/imprint.html' : AppConfig.imprint);
Pages.versionString = "CryptPad v3.19.1 (Thylacine's revenge)";
Pages.versionString = "CryptPad v3.20.0 (UplandMoa)";
// used for the about menu
Pages.imprintLink = AppConfig.imprint ? footLink(imprintUrl, 'imprint') : undefined;

2
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "cryptpad",
"version": "3.19.1",
"version": "3.20.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
"version": "3.19.1",
"version": "3.20.0",
"license": "AGPL-3.0+",
"repository": {
"type": "git",

@ -105,6 +105,12 @@
.markdown_preformatted-code;
.markdown_gfm-table(black);
table {
margin-bottom: 1rem;
}
media-tag > * {
margin-bottom: 1rem;
}
}
.cp-splitter {

@ -30,7 +30,6 @@ define([
var Mermaid = {
__stubbed: true,
init: function () {
var args = Util.slice(arguments);
require([
'mermaid',
'css!/code/mermaid-new.css'
@ -44,7 +43,6 @@ define([
});
}
Mermaid.init.call(args);
pluginLoaded.fire();
});
}
@ -88,7 +86,7 @@ define([
};
var sfCommon;
var fixMathjaxClickables = function ($svg) {
var fixMarkmapClickables = function ($svg) {
// find all links in the tree and do the following for each one
var onClick = function (e) {
e.preventDefault();
@ -132,7 +130,7 @@ define([
var data = MarkMapTransform.transform($el[0].getAttribute("markmap-source"));
$el[0].innerHTML = "<svg width='100%' height='600'/>";
Markmap.markmap($el[0].firstChild, data);
fixMathjaxClickables($el);
fixMarkmapClickables($el);
};
var highlighter = function () {
@ -191,17 +189,14 @@ define([
var mediaMap = {};
var defaultCode = renderer.code;
renderer.code = function (code, language) {
if (language === 'mermaid' && code.match(/^(graph|pie|gantt|sequenceDiagram|classDiagram|gitGraph)/)) {
return '<pre class="mermaid" data-plugin="mermaid">'+Util.fixHTML(code)+'</pre>';
} else if (language === 'markmap') {
return '<pre class="markmap" data-plugin="markmap">'+Util.fixHTML(code)+'</pre>';
} else if (language === 'mathjax') {
var svg = Mathjax.tex2svg(code, {display: true});
if (!svg) {
return defaultCode.apply(renderer, arguments);
}
return '<pre class="mathjax">'+ svg.innerHTML.replace(/xlink:href/g, "href") +'</pre>';
return '<pre class="mathjax" data-plugin="mathjax">'+Util.fixHTML(code)+'</pre>';
} else {
return defaultCode.apply(renderer, arguments);
}
@ -443,6 +438,58 @@ define([
}
};
plugins.mathjax = {
name: 'mathjax',
attr: 'mathjax-source',
render: function renderMathjax ($el) {
var el = $el[0];
if (!el) { return; }
var code = el.getAttribute("mathjax-source");
var svg = Mathjax.tex2svg(code, {display: true});
if (!svg) { return; }
svg.innerHTML = svg.innerHTML.replace(/xlink:href/g, "href");
var wrapper = document.createElement('span');
wrapper.innerHTML = svg.innerHTML;
el.innerHTML = wrapper.outerHTML;
}
};
var getAvailableCachedElement = function ($content, cache, src) {
var cached = cache[src];
if (!Array.isArray(cached)) { return; }
var root = $content[0];
var l = cached.length;
for (var i = 0; i < l; i++) {
if (!root.contains(cached[i])) {
return cached[i];
}
}
};
var cacheRenderedElement = function (cache, src, el) {
if (Array.isArray(cache[src])) {
cache[src].push(el);
} else {
cache[src] = [ el ];
}
};
// remove elements from the cache that are not embedded in the dom
var clearUnusedCacheEntries = function ($content, plugins) {
var root = $content[0];
Object.keys(plugins).forEach(function (name) {
var plugin = plugins[name];
var cache = plugin.cache;
Object.keys(cache).forEach(function (key) {
var list = cache[key];
if (!Array.isArray(list)) { return; }
cache[key] = list.filter(function (el) {
return root.contains(el);
});
});
});
};
DiffMd.apply = function (newHtml, $content, common) {
if (!sfCommon) { sfCommon = common; }
@ -514,7 +561,7 @@ define([
} else if (el.childNodes.length === 1 && el.childNodes[0].nodeType !== 3) {
// otherwise, confirm that the content of the rendered chart is not a text node
// and keep a copy of it
plugin.cache[src] = el.childNodes[0];
cacheRenderedElement(plugin.cache, src, el.childNodes[0]);
}
});
@ -550,7 +597,8 @@ define([
// Find initial position
// If the element is a mermaid or markmap svg, get the corresponding attribute
// If the element is supported by one of our plugin types
// (mermaid, mathjax, or markmap) get the corresponding attribute
var isSvg = $mt.is('pre[data-plugin]');
var plugin = isSvg && plugins[$mt.attr('data-plugin')];
@ -652,7 +700,7 @@ define([
if (target) { target.scrollIntoView(); }
});
// loop over mermaid elements in the rendered content
// loop over plugin elements in the rendered content
$content.find('pre[data-plugin]').each(function (index, el) {
var plugin = plugins[el.getAttribute('data-plugin')];
if (!plugin) { return; }
@ -674,7 +722,7 @@ define([
// of those in the markdown source.
var src = plugin.source[index];
el.setAttribute(plugin.attr, src);
var cached = plugin.cache[src];
var cached = getAvailableCachedElement($content, plugin.cache, src);
// check if you had cached a pre-rendered instance of the supplied source
if (typeof(cached) !== 'object') {
@ -694,6 +742,8 @@ define([
el.setAttribute('data-processed', true);
});
}
clearUnusedCacheEntries($content, plugins);
// recover the previous scroll position to avoid jank
$parent.scrollTop(scrollTop);
};

@ -233,7 +233,7 @@
"poll_removeOption": "Bist du sicher, dass du diese Option entfernen möchtest?",
"poll_removeUser": "Bist du sicher, dass du diesen Nutzer entfernen möchtest?",
"poll_titleHint": "Titel",
"poll_descriptionHint": "Beschreibe deine Abstimmung und publiziere sie mit der Schaltfläche ✓ (Veröffentlichen), wenn du fertig bist. Bei der Beschreibung kann Markdown-Syntax verwendet werden und du kannst Medien-Elemente von deinem CryptDrive einbetten. Jeder, der den Link kennt, kann die Beschreibung ändern. Dies wird aber nicht empfohlen.",
"poll_descriptionHint": "Beschreibe deine Abstimmung und veröffentliche sie mit der Schaltfläche ✓ (Veröffentlichen).\nBei der Beschreibung kann Markdown-Syntax verwendet werden und du kannst Medien-Elemente von deinem CryptDrive einbetten.\nJeder, der den Link kennt, kann die Beschreibung ändern. Dies wird aber nicht empfohlen.",
"poll_remove": "Entfernen",
"poll_edit": "Bearbeiten",
"poll_locked": "Gesperrt",
@ -327,9 +327,9 @@
"fm_openParent": "Im Ordner zeigen",
"fm_noname": "Dokument ohne Titel",
"fm_emptyTrashDialog": "Soll der Papierkorb wirklich geleert werden?",
"fm_removeSeveralPermanentlyDialog": "Bist du sicher, dass du diese {0} Elemente endgültig aus deinem CryptDrive entfernen möchtest?",
"fm_removeSeveralPermanentlyDialog": "Bist du sicher, dass du diese {0} Elemente aus deinem CryptDrive entfernen möchtest? Sie verbleiben in den CryptDrives anderer Benutzer, die sie gespeichert haben.",
"fm_removePermanentlyNote": "Wenn du fortfährst, werden deine eigenen Pads vom Server entfernt.",
"fm_removePermanentlyDialog": "Bist du sicher, dass du dieses Element endgültig aus deinem CryptDrive entfernen möchtest?",
"fm_removePermanentlyDialog": "Bist du sicher, dass du dieses Element aus deinem CryptDrive entfernen möchtest? Es verbleibt in den CryptDrives anderer Benutzer, die es gespeichert haben.",
"fm_removeSeveralDialog": "Bist du sicher, dass du diese {0} Elemente in den Papierkorb verschieben möchtest?",
"fm_removeDialog": "Bist du sicher, dass du {0} in den Papierkorb verschieben möchtest?",
"fm_deleteOwnedPad": "Bist du sicher, dass du dieses Pad endgültig vom Server löschen möchtest?",
@ -373,9 +373,9 @@
"fc_open": "Öffnen",
"fc_open_ro": "Öffnen (schreibgeschützt)",
"fc_delete": "In den Papierkorb verschieben",
"fc_delete_owned": "Vom Server löschen",
"fc_delete_owned": "Zerstören",
"fc_restore": "Wiederherstellen",
"fc_remove": "Aus deinem CryptDrive entfernen",
"fc_remove": "Entfernen",
"fc_remove_sharedfolder": "Entfernen",
"fc_empty": "Den Papierkorb leeren",
"fc_prop": "Eigenschaften",
@ -605,7 +605,7 @@
"blog": "Blog",
"topbar_whatIsCryptpad": "Was ist CryptPad",
"whatis_title": "Was ist CryptPad",
"whatis_collaboration": "Effektive und und leichte Zusammenarbeit",
"whatis_collaboration": "Effektive und leichte Zusammenarbeit",
"whatis_collaboration_p1": "Mit CryptPad kannst du kollaborative Dokumente erstellen, um Notizen und Ideen gemeinsam zu bearbeiten. Wenn du dich registrierst und einloggst, bekommst du die Möglichkeit, Dateien hochzuladen und Ordner einzurichten, um alle deine Dokumente zu organisieren. Als registrierter Nutzer erhältst du kostenlos 50 MB Speicherplatz.",
"whatis_collaboration_p2": "Du kannst den Zugang zu einem CryptPad-Dokument teilen, indem du einfach den entsprechenden Link teilst. Du kannst auch einen <em>schreibgeschützten</em> Zugang erstellen, um die Ergebnisse deiner Arbeit zu teilen, während du sie noch bearbeitest.",
"whatis_collaboration_p3": "Du kannst Rich-Text Dokumente mit dem <a href=\"http://ckeditor.com/\">CKEditor</a> erstellen. Außerdem kannst du Markdown-Dokumente erstellen, die in Echtzeit formatiert angezeigt werden, während du tippst. Du kannst auch die Umfrage-Anwendung verwenden, um Termine unter mehrere Teilnehmern zu abzustimmen.",
@ -720,7 +720,7 @@
},
"register": {
"q": "Weisst der Server mehr über mich, wenn ich registriere?",
"a": "Wir verlangen nicht Deine Emailadresse und der Server kennt Benutzername und Passwort auch dann nicht, wenn du dich registrierst. Statt dessen generiert das Registrierungs- und Anmeldeformular ein Schlüsselpaar mit deiner Eingabe. Nur der öffentliche Schlüssel dieses Schlüsselpaars wird zum Server geschickt. Mit diesem öffentlichen Schlüssel könenn wir z.B. die Menge der Daten, die du benutzt, kontrollieren, denn jeder Benutzer hat eine beschränkte Quota.<br><br> Wir benutzen die <em>Rückmeldung</em>s-Funktion, um den Server zu informieren, dass jemand mit deiner IP ein Konto registriert hat. Damit können wir messen, wie viele Benutzer CryptPad Konten registrieren und aus welchen Regionen. Somit können wir erfahren, welche Sprache besseren Support braucht.<br><br> Wenn Du registrierst, erstellst Du einen öffentlichen Schlüssel, der benutzt wird, um den Server zu informieren, dass er Dokumente auch dann nicht löschen sollte, wenn sie nicht aktiv benutzt werden. Diese Information zeigt dem Server, wie Du CryptPad benutzt und dieses System erlaubt uns, die Dokumente zu löschen, wofür sich keiner mehr interessiert."
"a": "Wir verlangen deine E-Mail-Adresse nicht, und der Server kennt Benutzername und Passwort auch dann nicht, wenn du dich registrierst. Statt dessen generiert das Registrierungs- und Anmeldeformular ein Schlüsselpaar aus deiner Eingabe. Nur der öffentliche Schlüssel dieses Schlüsselpaars wird zum Server geschickt. Mit diesem öffentlichen Schlüssel können wir z.B. die Menge der Daten, die du benutzt, kontrollieren, denn jeder Benutzer hat eine beschränkte Quota.<br><br>Wir benutzen die <em>Rückmeldung</em>s-Funktion, um den Server zu informieren, dass jemand mit deiner IP ein Konto registriert hat. Damit können wir messen, wie viele Benutzer CryptPad Konten registrieren und aus welchen Regionen. Somit können wir erfahren, welche Sprache besser unterstützt werden sollte.<br><br>Registrierte Benutzer informieren den Server, dass er Dokumente im CryptDrive auch dann nicht wegen Inaktivität löschen sollte, wenn sie nicht aktiv benutzt werden."
},
"other": {
"q": "Was können andere Benutzer über mich erfahren?",
@ -770,7 +770,7 @@
},
"remove": {
"q": "Ich habe ein Dokument aus meinem CryptDrive gelöscht, aber der Inhalt ist noch verfügbar. Wie kann ich es entfernen?",
"a": "Nur <em>eigene Pads</em>, die im Februar 2018 eingeführt wurden, können gelöscht werden und zwar nur von deren Eigentümer (der Benutzer, der das Dokument ursprünglich erstellt hat). Wenn du nicht der Eigentümer des Pads bist, musst du den Eigentümer bitten, dass er dieses für dich löscht. Bei Pads, deren Eigentümer du bist, kannst du <strong>auf das Pad in deinem CryptDrive rechtsklicken</em> und <strong>Vom Server löschen</strong> wählen."
"a": "Nur <em>eigene Pads</em>, die im Februar 2018 eingeführt wurden, können gelöscht werden und zwar nur von deren <em>Eigentümer</em> (der Benutzer, der das Dokument ursprünglich erstellt hat). Wenn du nicht der Eigentümer des Pads bist, musst du den Eigentümer bitten, dass er dieses für dich löscht. Bei Pads, deren Eigentümer du bist, kannst du <strong>auf das Pad in deinem CryptDrive rechtsklicken</strong> und <strong>Vom Server löschen</strong> wählen."
},
"forget": {
"q": "Was passiert, wenn ich mein Passwort vergesse?",
@ -797,7 +797,7 @@
"title": "Andere Fragen",
"pay": {
"q": "Wieso soll ich zahlen, wenn so viele Funktionen sowieso kostenfrei sind?",
"a": "Wir geben Unterstützern zusätzlichen Speicherplatz sowie die Möglichkeit, die Speicherplatzbegrenzung ihrer Kontakte zu erhöhen (<a href='https://accounts.cryptpad.fr/#/faq' target='_blank'>erfahre mehr</a>).<br><br>Über diese diese kurzfristigen Vorteile hinaus kannst du, wenn du ein Premiumangebot annimmst, die aktive Weiterentwicklung von CryptPad fördern. Das beinhaltet, Fehler zu beseitigen, neue Funktionen zu umzusetzen und Installationen von CryptPad auf eigenen Servern zu erleichtern. Zusätzlich hilfst du, anderen Anbietern zu beweisen, dass Leute datenschutzfreundliche Technologien unterstützen. Wir hoffen, dass Geschäftsmodelle, die auf dem Verkauf von Benutzerdaten basieren, letztendlich der Vergangenheit angehören werden.<br><br>Außerdem glauben wir, dass es gut ist, die Funktionen von CryptPad kostenfrei anzubieten. Denn jeder verdient persönlichen Datenschutz und nicht nur Personen mit hohem Einkommen. Durch deine Unterstützung hilfst du uns, zu ermöglichen, dass auch Menschen mit geringerem Einkommen diese grundlegenden Funktionen genießen können, ohne dass ein Preisetikett daran klebt."
"a": "Wir geben Unterstützern zusätzlichen Speicherplatz sowie die Möglichkeit, die Speicherplatzbegrenzung ihrer Kontakte zu erhöhen (<a href='https://accounts.cryptpad.fr/#/faq' target='_blank'>erfahre mehr</a>).<br><br>Über diese kurzfristigen Vorteile hinaus kannst du, wenn du ein Premiumangebot annimmst, die aktive Weiterentwicklung von CryptPad fördern. Das beinhaltet, Fehler zu beseitigen, neue Funktionen umzusetzen und Installationen von CryptPad auf eigenen Servern zu erleichtern. Zusätzlich hilfst du, anderen Anbietern zu beweisen, dass Benutzer datenschutzfreundliche Technologien unterstützen. Wir hoffen, dass Geschäftsmodelle, die auf dem Verkauf von Benutzerdaten basieren, letztendlich der Vergangenheit angehören werden.<br><br>Außerdem glauben wir, dass es gut ist, die Funktionen von CryptPad kostenfrei anzubieten. Denn jeder verdient persönlichen Datenschutz und nicht nur Personen mit hohem Einkommen. Durch deine Unterstützung hilfst du uns, zu ermöglichen, dass auch Menschen mit geringerem Einkommen diese grundlegenden Funktionen genießen können, ohne dass ein Preisetikett daran klebt."
},
"goal": {
"q": "Was ist euer Ziel?",
@ -906,7 +906,7 @@
"shortcuts": "Mit den Tastenkürzeln `Strg+b`, `Strg+i` und `Strg+u` formatierst du Text fett, kursiv oder unterstrichen.",
"indent": "In nummerierten Listen oder Aufzählungen kannst du mit Tab und Umschalt+Tab den Einzug erhöhen oder reduzieren."
},
"feedback_about": "Wenn du das liest, fragst du dich wahrscheinlich, weshalb dein Browser bei der der Ausführung mancher Aktionen Anfragen an Webseiten sendet",
"feedback_about": "Wenn du das liest, fragst du dich wahrscheinlich, weshalb dein Browser bei der Ausführung mancher Aktionen Anfragen an Webseiten sendet",
"feedback_privacy": "Wir respektieren deine Datenschutz, aber gleichzeitig wollen wir, dass die Benutzung von CryptPad sehr leicht ist. Deshalb wollen wir erfahren, welche Funktion am wichtigsten für unsere Benutzer ist, indem wir diese mit einer genauen Parameterbeschreibung anfordern.",
"feedback_optout": "Wenn du das nicht möchtest, kannst du es in <a href='/settings/'>deinen Einstellungen</a> deaktivieren",
"creation_404": "Dieses Pad existiert nicht mehr. Benutze das folgende Formular, um ein neues Pad zu erstellen.",
@ -1395,5 +1395,7 @@
"oo_refresh": "Neu laden",
"support_category": "Wähle eine Kategorie",
"oo_refreshText": "Dieses Dokument wurde aktualisiert",
"support_formCategoryError": "Fehler: Kategorie ist leer"
"support_formCategoryError": "Fehler: Kategorie ist leer",
"fm_restricted": "Du kannst auf dieses Element nicht zugreifen",
"fm_emptyTrashOwned": "In deinem Papierkorb sind Dokumente gespeichert, deren Eigentümer du bist. Du kannst sie aus deinem CryptDrive <b>entfernen</b> oder für alle Benutzer <b>zerstören</b>."
}

@ -203,7 +203,7 @@ define([
$p.append($('<br>'));
$('<button>', {
title: Messages.filePickerButton,
'class': '',
'class': 'btn',
style: 'font-size: 17px',
id: 'cp-app-slide-options-bg'
}).click(function () {
@ -221,16 +221,18 @@ define([
}
});
}).text(Messages.printBackgroundButton).appendTo($p);
$p.append($('<br>'));
}
$p.append($('<br>'));
var $bgValue = $('<div>').appendTo($p);
var $bgValue = $('<div class="cp-background-selected">').appendTo($p);
var refreshValue = function () {
$bgValue.html('');
if (slideOptionsTmp.background && slideOptionsTmp.background.name) {
$bgValue.append(Messages._getKey("printBackgroundValue", [slideOptionsTmp.background.name]));
$('<button>', {
$('<span>', {
'class': 'fa fa-times',
title: Messages.printBackgroundRemove
title: Messages.printBackgroundRemove,
style: 'margin-left: 5px'
}).click(function () {
slideOptionsTmp.background = false;
refreshValue();
@ -247,7 +249,6 @@ define([
};
}
$p.append($('<br>'));
$p.append($('<br>'));
// CSS
$('<label>', {'for': 'cp-app-slide-options-css'}).text(Messages.printCSS).appendTo($p);
$p.append($('<br>'));
@ -307,8 +308,8 @@ define([
h = UI.listenForKeys(todo, todoCancel);
var $nav = $('<nav>').appendTo($div);
$('<button>', {'class': 'cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel);
$('<button>', {'class': 'ok'}).text(Messages.settings_save).appendTo($nav).click(todo);
$('<button>', {'class': 'btn cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel);
$('<button>', {'class': 'btn ok'}).text(Messages.settings_save).appendTo($nav).click(todo);
return $container;
};
@ -484,15 +485,19 @@ define([
CodeMirror.init(framework.localChange, framework._.title, framework._.toolbar);
CodeMirror.configureTheme(common);
var drawSlides = Util.throttle(function (content) {
Slide.update(content);
}, 400);
framework.onContentUpdate(function (newContent) {
CodeMirror.contentUpdate(newContent);
Slide.update(newContent.content);
drawSlides(newContent.content);
});
framework.setContentGetter(function () {
CodeMirror.removeCursors();
var content = CodeMirror.getContent();
Slide.update(content.content);
drawSlides(content.content);
return content;
});

@ -154,18 +154,22 @@ define([
updateFontSize();
};
Slide.update = function (content) {
Slide.update = function (content, force) {
updateFontSize();
if (!content) { content = ''; }
var old = Slide.content;
Slide.content = content.replace(/\n\s*\-\-\-\s*\n/g, '\n\n'+separator+'\n\n');
if (old !== Slide.content) {
if (force || old !== Slide.content) {
draw(Slide.index);
return;
}
change(Slide.lastIndex, Slide.index);
};
DiffMd.onPluginLoaded(function () {
Slide.update(Slide.content, true);
});
Slide.left = function () {
console.log('left');
Slide.lastIndex = Slide.index;

Loading…
Cancel
Save