Merge remote-tracking branch 'origin/staging' into staging

pull/1/head
David Benqué 4 years ago
commit ffe0dfdf8d

@ -996,6 +996,9 @@
.cp-toolbar-tools { .cp-toolbar-tools {
order: 7; order: 7;
} }
.cp-toolbar-icon-pad_toc {
order: 8;
}
.cp-toolbar-file { .cp-toolbar-file {
button { button {
&.fa-plus { order: 0; } &.fa-plus { order: 0; }

22
package-lock.json generated

@ -393,12 +393,12 @@
} }
}, },
"dot-prop": { "dot-prop": {
"version": "4.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
"dev": true, "dev": true,
"requires": { "requires": {
"is-obj": "^1.0.0" "is-obj": "^2.0.0"
} }
}, },
"ecc-jsbn": { "ecc-jsbn": {
@ -770,9 +770,9 @@
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
}, },
"is-obj": { "is-obj": {
"version": "1.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
"dev": true "dev": true
}, },
"is-typedarray": { "is-typedarray": {
@ -1243,12 +1243,12 @@
} }
}, },
"postcss-selector-parser": { "postcss-selector-parser": {
"version": "3.1.1", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
"integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
"dev": true, "dev": true,
"requires": { "requires": {
"dot-prop": "^4.1.1", "dot-prop": "^5.2.0",
"indexes-of": "^1.0.1", "indexes-of": "^1.0.1",
"uniq": "^1.0.1" "uniq": "^1.0.1"
} }

@ -4104,5 +4104,11 @@ define([
}; };
}; };
UIElements.isVisible = function (el, $container) {
var size = $container.outerHeight();
var pos = el.getBoundingClientRect();
return (pos.bottom < size) && (pos.y > 0);
};
return UIElements; return UIElements;
}); });

@ -1398,5 +1398,6 @@
"fm_restricted": "Vous n'avez pas accès à cet élément", "fm_restricted": "Vous n'avez pas accès à cet élément",
"fm_emptyTrashOwned": "Votre corbeille contient des documents dont vous êtes propriétaire. Vous pouvez les <b>supprimer</b> de votre drive uniquement, ou les <b>détruire</b> pour tous les utilisateurs.", "fm_emptyTrashOwned": "Votre corbeille contient des documents dont vous êtes propriétaire. Vous pouvez les <b>supprimer</b> de votre drive uniquement, ou les <b>détruire</b> pour tous les utilisateurs.",
"fm_noResult": "Pas de résultat", "fm_noResult": "Pas de résultat",
"support_formCategoryError": "Erreur : la catégorie est vide" "support_formCategoryError": "Erreur : la catégorie est vide",
"pad_tocHide": "Plan"
} }

@ -177,5 +177,101 @@
"profileButton": "プロフィール", "profileButton": "プロフィール",
"profile_urlPlaceholder": "URL", "profile_urlPlaceholder": "URL",
"profile_avatar": "アバター", "profile_avatar": "アバター",
"profile_upload": " 新しいアバターをアップロード" "profile_upload": " 新しいアバターをアップロード",
"teams_table_generic_edit": "編集: フォルダとパッドの作成、変更、削除が可能。",
"teams_table_generic_view": "表示: フォルダとパッドへのアクセス(閲覧のみ)。",
"teams_table_generic_own": "チームの管理: チーム名とチームアバターの変更、所有者の追加または削除、チームのサブスクリプションの変更、チームの削除が可能。",
"teams_table_owners": "チームの管理",
"teams_table_generic_admin": "メンバーの管理: メンバーの招待および取り消し、メンバーに管理者までの権限の付与が可能。",
"teams_table_admins": "メンバーの管理",
"teams_table_generic": "権限一覧",
"teams_table": "権限",
"contacts_fetchHistory": "古い履歴を取得する",
"contacts_warning": "ここに入力したすべてのものは永続的であり、このパッドの現在および将来のすべてのユーザーが利用できます。機密情報の入力は推奨されません!",
"contacts_typeHere": "メッセージを入力...",
"team_listLoad": "開く",
"team_cat_drive": "ドライブ",
"team_cat_chat": "チャット",
"team_cat_members": "メンバー",
"team_cat_admin": "管理",
"adminPage": "管理",
"team_deleteButton": "削除",
"team_deleteHint": "チーム自体とチームが所有しているすべてのドキュメントを削除します。",
"team_deleteTitle": "チームの削除",
"team_avatarHint": "容量 500KB 以下 (png 、jpg 、jpeg 、gif)",
"team_avatarTitle": "チームアバター",
"team_nameHint": "チームの名前を設定します",
"team_nameTitle": "チーム名",
"team_members": "メンバー",
"team_owner": "所有者",
"team_admins": "管理者",
"editors": "編集者",
"viewers": "閲覧者",
"contacts_padTitle": "チャット",
"chatButton": "チャット",
"contacts_unmute": "ミュート解除",
"contacts_mute": "ミュート",
"contacts": "連絡先",
"share_linkOpen": "プレビュー",
"share_linkView": "表示",
"view": "表示",
"settings_exportError": "表示エラー",
"pad_mediatagPreview": "プレビュー",
"share_linkAccess": "アクセス権限",
"viewer": "閲覧者",
"reconnecting": "再接続中",
"synchronizing": "同期中",
"initializing": "初期化中...",
"yourself": "あなた",
"anonymous": "匿名",
"editor": "編集者",
"anonymousUser": "匿名の編集者",
"anonymousUsers": "匿名の編集者",
"typing": "編集中",
"team_infoLabel": "チームについて",
"support_cat_all": "全て",
"support_addAttachment": "添付ファイルを追加",
"support_attachments": "添付ファイル",
"support_cat_bug": "バグの報告",
"support_cat_data": "コンテンツの損失",
"support_cat_account": "ユーザーアカウント",
"support_formCategoryError": "エラー: カテゴリーが選択されていません",
"support_category": "カテゴリーを選択",
"support_languagesPreamble": "サポートチームは次の言語に対応可能です:",
"support_listHint": "管理者に送信されたチケットとその回答のリストは以下の通りです。閉じたチケットを再開することはできませんが、新しいチケットを作成することはできます。閉じたチケットは非表示にできます。",
"support_listTitle": "サポートチケット",
"settings_padNotifCheckbox": "コメント通知を無効化",
"settings_padNotifTitle": "コメント通知",
"notifications_dismissAll": "全て確認済みにする",
"notifications_cat_archived": "履歴",
"notifications_cat_friends": "連絡先リクエスト",
"notifications_dismiss": "確認済みにする",
"settings_autostoreMaybe": "手動 (確認しない)",
"settings_autostoreNo": "手動 (常に確認する)",
"settings_autostoreHint": "<b>自動</b> あなたがアクセスしたすべてのパッドを、あなたの CryptDrive に保存します。<br><b>手動 (常に確認する)</b> まだ保存していないパッドにアクセスした場合に、あなたの CryptDrive に保存するかどうか尋ねます。<br><b>手動 (確認しない)</b> アクセス先のパッドがあなたの CryptDrive に自動的に保存されなくなります。保存オプションは表示されなくなります。",
"settings_userFeedback": "ユーザーフィードバックを有効化",
"settings_userFeedbackHint2": "あなたのパッドのコンテンツがサーバーと共有されることはありません。",
"settings_userFeedbackHint1": "CryptPad は、あなたの経験を向上させる方法を知るために、サーバーにいくつかの非常に基本的なフィードバックを提供します。 ",
"settings_userFeedbackTitle": "フィードバック",
"settings_autostoreYes": "自動",
"settings_importConfirm": "このブラウザで最近使用したパッドを、あなたのユーザーアカウントの CryptDrive にインポートしますか?",
"settings_importDone": "インポートが完了しました",
"settings_import": "インポート",
"settings_importTitle": "このブラウザでの最近のパッドをあなたの CryptDrive にインポートします",
"settings_trimHistoryHint": "ドライブと通知の履歴を削除して、ストレージ容量を節約します。これはパッドの履歴には影響しません。パッドの履歴は、プロパティダイアログから削除できます。",
"trimHistory_currentSize": "現在の履歴容量: <b>{0}</b>",
"support_cat_other": "その他",
"user_about": "CryptPad について",
"fc_delete": "ごみ箱へ移動",
"fc_remove": "削除",
"fc_restore": "復元",
"fc_delete_owned": "完全削除",
"creation_create": "作成",
"creation_password": "パスワードの追加",
"creation_expireMonths": "か月",
"creation_expireDays": "日",
"creation_expireHours": "時間",
"creation_expireFalse": "無制限",
"pad_wordCount": "単語数: {0}",
"teams_table_role": "権限"
} }

@ -1398,5 +1398,6 @@
"support_formCategoryError": "Error: category is empty", "support_formCategoryError": "Error: category is empty",
"fm_emptyTrashOwned": "Your trash contains documents you own. You can <b>remove</b> them from your drive only, or <b>destroy</b> them for all users.", "fm_emptyTrashOwned": "Your trash contains documents you own. You can <b>remove</b> them from your drive only, or <b>destroy</b> them for all users.",
"fm_restricted": "You do not have access", "fm_restricted": "You do not have access",
"fm_noResult": "No results found" "fm_noResult": "No results found",
"pad_tocHide": "Outline"
} }

@ -24,6 +24,33 @@ body.cp-app-pad {
overflow: hidden; overflow: hidden;
} }
#cp-app-pad-toc {
@toc-level-indent: 15px;
margin-top: 10px;
margin-left: 10px;
width: 200px;
color: @cryptpad_text_col;
h2 {
font-size: 1.5rem;
}
p {
margin-bottom: 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
a {
color: @cryptpad_text_col;
}
&.cp-pad-toc-2 {
margin-left: @toc-level-indent;
}
&.cp-pad-toc-3 {
margin-left: @toc-level-indent * 2;
}
}
}
.cke_toolbox_main { .cke_toolbox_main {
background-color: @colortheme_pad-toolbar-bg; background-color: @colortheme_pad-toolbar-bg;
.cke_toolbar { .cke_toolbar {

@ -5,8 +5,9 @@ define([
'/common/common-hash.js', '/common/common-hash.js',
'/common/hyperscript.js', '/common/hyperscript.js',
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-ui-elements.js',
'/customize/messages.js' '/customize/messages.js'
], function($, Sortify, Util, Hash, h, UI, Messages) { ], function($, Sortify, Util, Hash, h, UI, UIElements, Messages) {
var Comments = {}; var Comments = {};
/* /*
@ -273,12 +274,6 @@ define([
]); ]);
}; };
var isVisible = function(el, $container) {
var size = $container.outerHeight();
var pos = el.getBoundingClientRect();
return (pos.bottom < size) && (pos.y > 0);
};
var redrawComments = function(Env) { var redrawComments = function(Env) {
// Don't redraw if there were no change // Don't redraw if there were no change
var str = Sortify(Env.comments || {}); var str = Sortify(Env.comments || {});
@ -558,7 +553,7 @@ define([
// Scroll into view // Scroll into view
if (!$last.length) { return; } if (!$last.length) { return; }
var visible = isVisible($last[0], Env.$inner); var visible = UIElements.isVisible($last[0], Env.$inner);
if (!visible) { $last[0].scrollIntoView(); } if (!visible) { $last[0].scrollIntoView(); }
}; };
@ -574,7 +569,7 @@ define([
focusContent(); focusContent();
var visible = isVisible(div, Env.$container); var visible = UIElements.isVisible(div, Env.$container);
if (!visible) { div.scrollIntoView(); } if (!visible) { div.scrollIntoView(); }
}); });

@ -45,7 +45,6 @@
<div id="cp-app-pad-toolbar" class="cp-toolbar-container"></div> <div id="cp-app-pad-toolbar" class="cp-toolbar-container"></div>
<div id="cp-app-pad-editor"> <div id="cp-app-pad-editor">
<textarea style="display:none" id="editor1" name="editor1"></textarea> <textarea style="display:none" id="editor1" name="editor1"></textarea>
<div id="cp-app-pad-comments"></div>
</div> </div>
</body> </body>
</html> </html>

@ -42,6 +42,7 @@ define([
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/hyperscript.js', '/common/hyperscript.js',
'/bower_components/chainpad/chainpad.dist.js', '/bower_components/chainpad/chainpad.dist.js',
'/customize/application_config.js', '/customize/application_config.js',
@ -69,6 +70,7 @@ define([
Hash, Hash,
Util, Util,
UI, UI,
UIElements,
h, h,
ChainPad, ChainPad,
AppConfig, AppConfig,
@ -424,6 +426,41 @@ define([
}); });
}; };
var addTOCHideBtn = function(framework, $toc) {
// Expand / collapse the toolbar
var onClick = function(visible) {
framework._.sfCommon.setAttribute(['pad', 'showTOC'], visible);
};
framework._.sfCommon.getAttribute(['pad', 'showTOC'], function(err, data) {
var state = false;
if (($(window).height() >= 800 || $(window).width() >= 800) &&
(typeof(data) === "undefined" || data)) {
state = true;
$toc.show();
} else {
$toc.hide();
}
var $tocButton = framework._.sfCommon.createButton('', true, {
drawer: false,
text: Messages.pad_tocHide,
name: 'pad_toc',
icon: 'fa-list-ul',
}, function () {
$tocButton.removeClass('cp-toolbar-button-active');
$toc.toggle();
state = $toc.is(':visible');
if (state) {
$tocButton.addClass('cp-toolbar-button-active');
}
onClick(state);
});
framework._.toolbar.$bottomL.append($tocButton);
if (state) {
$tocButton.addClass('cp-toolbar-button-active');
}
});
};
var displayMediaTags = function(framework, dom, mediaTagMap) { var displayMediaTags = function(framework, dom, mediaTagMap) {
setTimeout(function() { // Just in case setTimeout(function() { // Just in case
var tags = dom.querySelectorAll('media-tag:empty'); var tags = dom.querySelectorAll('media-tag:empty');
@ -537,6 +574,9 @@ define([
$container: $('#cp-app-pad-comments') $container: $('#cp-app-pad-comments')
}); });
var $toc = $('#cp-app-pad-toc');
addTOCHideBtn(framework, $toc);
// My cursor // My cursor
var cursor = module.cursor = Cursor(inner); var cursor = module.cursor = Cursor(inner);
@ -607,6 +647,34 @@ define([
}, 500); // 500ms to make sure it is sent after chainpad sync }, 500); // 500ms to make sure it is sent after chainpad sync
}; };
var updateTOC = Util.throttle(function () {
var toc = [];
$inner.find('h1, h2, h3').each(function (i, el) {
toc.push({
level: Number(el.tagName.slice(1)),
el: el,
title: Util.stripTags($(el).text())
});
});
var content = [h('h2', Messages.markdown_toc)];
toc.forEach(function (obj) {
// Only include level 2 headings
var level = obj.level;
var a = h('a.cp-pad-toc-link', {
href: '#',
});
$(a).click(function (e) {
e.preventDefault();
e.stopPropagation();
if (!obj.el || UIElements.isVisible(obj.el, $inner)) { return; }
obj.el.scrollIntoView();
});
a.innerHTML = obj.title;
content.push(h('p.cp-pad-toc-'+level, a));
});
$toc.html('').append(content);
});
// apply patches, and try not to lose the cursor in the process! // apply patches, and try not to lose the cursor in the process!
framework.onContentUpdate(function(hjson) { framework.onContentUpdate(function(hjson) {
if (!Array.isArray(hjson)) { throw new Error(Messages.typeError); } if (!Array.isArray(hjson)) { throw new Error(Messages.typeError); }
@ -666,6 +734,8 @@ define([
} }
comments.onContentUpdate(); comments.onContentUpdate();
updateTOC();
}); });
framework.setTextContentGetter(function() { framework.setTextContentGetter(function() {
@ -877,8 +947,12 @@ define([
framework.localChange(); framework.localChange();
updateCursor(); updateCursor();
editor.fire('cp-wc'); // Update word count editor.fire('cp-wc'); // Update word count
updateTOC();
});
editor.on('change', function () {
framework.localChange();
updateTOC();
}); });
editor.on('change', framework.localChange);
var wordCount = h('span.cp-app-pad-wordCount'); var wordCount = h('span.cp-app-pad-wordCount');
$('.cke_toolbox_main').append(wordCount); $('.cke_toolbox_main').append(wordCount);
@ -1077,6 +1151,7 @@ define([
var $ckeToolbar = $('#cke_1_top').find('.cke_toolbox_main'); var $ckeToolbar = $('#cke_1_top').find('.cke_toolbox_main');
$mainContainer.prepend($ckeToolbar.addClass('cke_reset_all')); $mainContainer.prepend($ckeToolbar.addClass('cke_reset_all'));
$contentContainer.append(h('div#cp-app-pad-comments')); $contentContainer.append(h('div#cp-app-pad-comments'));
$contentContainer.prepend(h('div#cp-app-pad-toc'));
$ckeToolbar.find('.cke_button__image_icon').parent().hide(); $ckeToolbar.find('.cke_button__image_icon').parent().hide();
}).nThen(waitFor()); }).nThen(waitFor());

@ -1,19 +1,28 @@
define([ define([
'jquery', 'jquery',
'/common/hyperscript.js', '/common/hyperscript.js',
'/common/common-ui-elements.js',
'/customize/messages.js' '/customize/messages.js'
], function ($, h, Messages) { ], function ($, h, UIElements, Messages) {
var onLinkClicked = function (e, inner) { var onLinkClicked = function (e, inner) {
var $target = $(e.target); var $target = $(e.target);
if (!$target.is('a')) { return; } if (!$target.is('a')) { return; }
var href = $target.attr('href'); var href = $target.attr('href');
if (!href || href[0] === '#') { return; } if (!href) { return; }
var $inner = $(inner);
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (href[0] === '#') {
var anchor = $inner.find(href);
if (!anchor.length) { return; }
anchor[0].scrollIntoView();
return;
}
var $iframe = $('html').find('iframe').contents(); var $iframe = $('html').find('iframe').contents();
var $inner = $(inner);
var rect = e.target.getBoundingClientRect(); var rect = e.target.getBoundingClientRect();
var rect0 = inner.getBoundingClientRect(); var rect0 = inner.getBoundingClientRect();

Loading…
Cancel
Save