mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
Merge remote-tracking branch 'origin/develop' into feature/syntax_highlight
This commit is contained in:
commit
0a6815e448
@ -551,7 +551,7 @@ export default class TabManager extends Component {
|
||||
await this.removeNoteContext(ntxIdToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async closeOtherTabsCommand({ntxId}) {
|
||||
for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
|
||||
if (ntxIdToRemove !== ntxId) {
|
||||
@ -560,6 +560,18 @@ export default class TabManager extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
async closeRightTabsCommand({ntxId}) {
|
||||
const ntxIds = this.mainNoteContexts.map(nc => nc.ntxId);
|
||||
const index = ntxIds.indexOf(ntxId);
|
||||
|
||||
if (index !== -1) {
|
||||
const idsToRemove = ntxIds.slice(index + 1);
|
||||
for (const ntxIdToRemove of idsToRemove) {
|
||||
await this.removeNoteContext(ntxIdToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async closeTabCommand({ntxId}) {
|
||||
await this.removeNoteContext(ntxId);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ const TPL = `
|
||||
</div>
|
||||
|
||||
<div class="delete-notes-list-wrapper">
|
||||
<h4>${t('delete_notes.notes_to_be_deleted')} (<span class="deleted-notes-count"></span>)</h4>
|
||||
<h4>${t('delete_notes.notes_to_be_deleted', { noteCount: '<span class="deleted-notes-count"></span>' })}</h4>
|
||||
|
||||
<ul class="delete-notes-list" style="max-height: 200px; overflow: auto;"></ul>
|
||||
</div>
|
||||
@ -36,7 +36,7 @@ const TPL = `
|
||||
|
||||
<div class="broken-relations-wrapper">
|
||||
<div class="alert alert-danger">
|
||||
<h4>${t('delete_notes.broken_relations_to_be_deleted')} (<span class="broke-relations-count"></span>)</h4>
|
||||
<h4>${t('delete_notes.broken_relations_to_be_deleted', { relationCount: '<span class="broke-relations-count"></span>'})}</h4>
|
||||
|
||||
<ul class="broken-relations-list" style="max-height: 200px; overflow: auto;"></ul>
|
||||
</div>
|
||||
@ -126,11 +126,11 @@ export default class DeleteNotesDialog extends BasicWidget {
|
||||
|
||||
for (const attr of response.brokenRelations) {
|
||||
this.$brokenRelationsList.append(
|
||||
$("<li>")
|
||||
.append(`${t('delete_notes.note')} `)
|
||||
.append(await linkService.createLink(attr.value))
|
||||
.append(` ${t('delete_notes.to_be_deleted', {attrName: attr.name})} `)
|
||||
.append(await linkService.createLink(attr.noteId))
|
||||
$("<li>").html(t("delete_notes.deleted_relation_text", {
|
||||
note: (await linkService.createLink(attr.value)).html(),
|
||||
relation: `<code>${attr.name}</code>`,
|
||||
source: (await linkService.createLink(attr.noteId)).html()
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -260,8 +260,10 @@ export default class TabRowWidget extends BasicWidget {
|
||||
y: e.pageY,
|
||||
items: [
|
||||
{title: t('tab_row.close'), command: "closeTab", uiIcon: "bx bx-x"},
|
||||
{title: t('tab_row.close_other_tabs'), command: "closeOtherTabs", uiIcon: "bx bx-x"},
|
||||
{title: t('tab_row.close_all_tabs'), command: "closeAllTabs", uiIcon: "bx bx-x"},
|
||||
{title: t('tab_row.close_other_tabs'), command: "closeOtherTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.length !== 1},
|
||||
{title: t('tab_row.close_right_tabs'), command: "closeRightTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.at(-1).ntxId !== ntxId},
|
||||
{title: t('tab_row.close_all_tabs'), command: "closeAllTabs", uiIcon: "bx bx-empty"},
|
||||
{ title: "----" },
|
||||
{title: t('tab_row.move_tab_to_new_window'), command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"}
|
||||
],
|
||||
selectMenuItemHandler: ({command}) => {
|
||||
|
@ -18,14 +18,28 @@ const TPL = `
|
||||
width: 130px;
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
padding; 10px;
|
||||
border: 1px transparent solid;
|
||||
}
|
||||
|
||||
|
||||
.workspace-notes .workspace-note:hover {
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
.note-detail-empty-results .aa-dropdown-menu {
|
||||
max-height: 50vh;
|
||||
overflow: scroll;
|
||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.empty-tab-search .note-autocomplete-input {
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.empty-tab-search .input-clearer-button {
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.workspace-icon {
|
||||
text-align: center;
|
||||
@ -33,14 +47,14 @@ const TPL = `
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="workspace-notes"></div>
|
||||
<div class="form-group empty-tab-search">
|
||||
<label>${t('empty.open_note_instruction')}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group mt-1">
|
||||
<input class="form-control note-autocomplete" placeholder="${t('empty.search_placeholder')}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="workspace-notes"></div>
|
||||
<div class="note-detail-empty-results"></div>
|
||||
</div>`;
|
||||
|
||||
export default class EmptyTypeWidget extends TypeWidget {
|
||||
@ -51,10 +65,12 @@ export default class EmptyTypeWidget extends TypeWidget {
|
||||
|
||||
this.$widget = $(TPL);
|
||||
this.$autoComplete = this.$widget.find(".note-autocomplete");
|
||||
this.$results = this.$widget.find(".note-detail-empty-results");
|
||||
|
||||
noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, {
|
||||
hideGoToSelectedNoteButton: true,
|
||||
allowCreatingNotes: true
|
||||
allowCreatingNotes: true,
|
||||
container: this.$results
|
||||
})
|
||||
.on('autocomplete:noteselected', function(event, suggestion, dataset) {
|
||||
if (!suggestion.notePath) {
|
||||
@ -66,6 +82,7 @@ export default class EmptyTypeWidget extends TypeWidget {
|
||||
|
||||
this.$workspaceNotes = this.$widget.find('.workspace-notes');
|
||||
|
||||
noteAutocompleteService.showRecentNotes(this.$autoComplete);
|
||||
super.doRender();
|
||||
}
|
||||
|
||||
|
@ -72,13 +72,12 @@
|
||||
"delete_all_clones_description": "同时删除所有克隆(可以在最近修改中撤消)",
|
||||
"erase_notes_description": "通常(软)删除仅标记笔记为已删除,可以在一段时间内通过最近修改对话框撤消。选中此选项将立即擦除笔记,不可撤销。",
|
||||
"erase_notes_warning": "永久擦除笔记(无法撤销),包括所有克隆。这将强制应用程序重新加载。",
|
||||
"notes_to_be_deleted": "将删除以下笔记(<span class=\"deleted-notes-count\"></span>)",
|
||||
"notes_to_be_deleted": "将删除以下笔记 ({{- noteCount}})",
|
||||
"no_note_to_delete": "没有笔记将被删除(仅克隆)。",
|
||||
"broken_relations_to_be_deleted": "将删除以下关系并断开连接(<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{- relationCount}})",
|
||||
"cancel": "取消",
|
||||
"ok": "确定",
|
||||
"note": "笔记",
|
||||
"to_be_deleted": " (将被删除的笔记) 被以下关系 <code>{{attrName}}</code> 引用, 来自 "
|
||||
"deleted_relation_text": "笔记 {{- note}} (将被删除的笔记) 被以下关系 {{- relation}} 引用, 来自 {{- source}}。"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "导出笔记",
|
||||
|
@ -75,16 +75,15 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Delete notes preview",
|
||||
"delete_all_clones_description": "delete also all clones (can be undone in recent changes)",
|
||||
"delete_all_clones_description": "Delete also all clones (can be undone in recent changes)",
|
||||
"erase_notes_description": "Normal (soft) deletion only marks the notes as deleted and they can be undeleted (in recent changes dialog) within a period of time. Checking this option will erase the notes immediately and it won't be possible to undelete the notes.",
|
||||
"erase_notes_warning": "erase notes permanently (can't be undone), including all clones. This will force application reload.",
|
||||
"notes_to_be_deleted": "Following notes will be deleted (<span class=\"deleted-notes-count\"></span>)",
|
||||
"erase_notes_warning": "Erase notes permanently (can't be undone), including all clones. This will force application reload.",
|
||||
"notes_to_be_deleted": "Following notes will be deleted ({{- noteCount}})",
|
||||
"no_note_to_delete": "No note will be deleted (only clones).",
|
||||
"broken_relations_to_be_deleted": "Following relations will be broken and deleted (<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "Following relations will be broken and deleted ({{- relationCount}})",
|
||||
"cancel": "Cancel",
|
||||
"ok": "OK",
|
||||
"note": "Note",
|
||||
"to_be_deleted": " (to be deleted) is referenced by relation <code>{{attrName}}</code> originating from "
|
||||
"deleted_relation_text": "Note {{- note}} (to be deleted) is referenced by relation {{- relation}} originating from {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Export note",
|
||||
@ -1434,6 +1433,7 @@
|
||||
"add_new_tab": "Add new tab",
|
||||
"close": "Close",
|
||||
"close_other_tabs": "Close other tabs",
|
||||
"close_right_tabs": "Close tabs to the right",
|
||||
"close_all_tabs": "Close all tabs",
|
||||
"move_tab_to_new_window": "Move this tab to a new window",
|
||||
"new_tab": "New tab"
|
||||
|
@ -75,16 +75,15 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Eliminar vista previa de notas",
|
||||
"delete_all_clones_description": "eliminar también todos los clones (se puede deshacer en cambios recientes)",
|
||||
"delete_all_clones_description": "Eliminar también todos los clones (se puede deshacer en cambios recientes)",
|
||||
"erase_notes_description": "La eliminación normal (suave) solo marca las notas como eliminadas y se pueden recuperar (en el cuadro de diálogo de cambios recientes) dentro de un periodo de tiempo. Al marcar esta opción se borrarán las notas inmediatamente y no será posible recuperarlas.",
|
||||
"erase_notes_warning": "eliminar notas permanentemente (no se puede deshacer), incluidos todos los clones. Esto forzará la recarga de la aplicación.",
|
||||
"notes_to_be_deleted": "Las siguientes notas serán eliminadas (<span class=\"deleted-notes-count\"></span>)",
|
||||
"erase_notes_warning": "Eliminar notas permanentemente (no se puede deshacer), incluidos todos los clones. Esto forzará la recarga de la aplicación.",
|
||||
"notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{- noteCount}})",
|
||||
"no_note_to_delete": "No se eliminará ninguna nota (solo clones).",
|
||||
"broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas (<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{- relationCount}})",
|
||||
"cancel": "Cancelar",
|
||||
"ok": "Aceptar",
|
||||
"note": "Nota",
|
||||
"to_be_deleted": " (para ser eliminada) está referenciado por la relación <code>{{attrName}}</code> que se origina en "
|
||||
"deleted_relation_text": "Nota {{- note}} (para ser eliminada) está referenciado por la relación {{- relation}} que se origina en {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exportar nota",
|
||||
|
@ -69,16 +69,15 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Supprimer l'aperçu des notes",
|
||||
"delete_all_clones_description": "supprime également tous les clones (peut être annulé depuis les Modifications récentes)",
|
||||
"delete_all_clones_description": "Supprime également tous les clones (peut être annulé depuis les Modifications récentes)",
|
||||
"erase_notes_description": "La suppression normale (douce) marque uniquement les notes comme supprimées et elles peuvent être restaurées (dans la boîte de dialogue des Modifications récentes) dans un délai donné. Cocher cette option effacera les notes immédiatement et il ne sera pas possible de les restaurer.",
|
||||
"erase_notes_warning": "efface les notes de manière permanente (ne peut pas être annulée), y compris tous les clones. Cela forcera le rechargement de l’application.",
|
||||
"notes_to_be_deleted": "Les notes suivantes seront supprimées (<span class=\"deleted-notes-count\"></span>)",
|
||||
"erase_notes_warning": "Efface les notes de manière permanente (ne peut pas être annulée), y compris tous les clones. Cela forcera le rechargement de l’application.",
|
||||
"notes_to_be_deleted": "Les notes suivantes seront supprimées ({{- noteCount}})",
|
||||
"no_note_to_delete": "Aucune note ne sera supprimée (uniquement les clones).",
|
||||
"broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées (<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{- relationCount}})",
|
||||
"cancel": "Annuler",
|
||||
"ok": "OK",
|
||||
"note": "Note",
|
||||
"to_be_deleted": " (à supprimer) est référencé par la relation <code>{{attrName}}</code> provenant de "
|
||||
"deleted_relation_text": "Note {{- note}} (à supprimer) est référencé par la relation {{- relation}} provenant de {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exporter la note",
|
||||
|
@ -414,17 +414,16 @@
|
||||
"undelete_notes_instruction": "După ștergere, se pot recupera din ecranul Schimbări recente."
|
||||
},
|
||||
"delete_notes": {
|
||||
"broken_relations_to_be_deleted": "Următoarele relații vor fi întrerupte și șterse (<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "Următoarele relații vor fi întrerupte și șterse ({{- relationCount}})",
|
||||
"cancel": "Anulează",
|
||||
"delete_all_clones_description": "Șterge și toate clonele (se pot recupera în ecranul Schimbări recente)",
|
||||
"delete_notes_preview": "Șterge previzualizările notițelor",
|
||||
"delete_notes_preview": "Previzualizare ștergerea notițelor",
|
||||
"erase_notes_description": "Ștergerea obișnuită doar marchează notițele ca fiind șterse și pot fi recuperate (în ecranul Schimbări recente) pentru o perioadă de timp. Dacă se bifează această opțiune, notițele vor fi șterse imediat fără posibilitatea de a le recupera.",
|
||||
"erase_notes_warning": "șterge notițele permanent (nu se mai pot recupera), incluzând toate clonele. Va forța reîncărcarea aplicației.",
|
||||
"erase_notes_warning": "Șterge notițele permanent (nu se mai pot recupera), incluzând toate clonele. Va forța reîncărcarea aplicației.",
|
||||
"no_note_to_delete": "Nicio notiță nu va fi ștearsă (doar clonele).",
|
||||
"note": "Notiță",
|
||||
"notes_to_be_deleted": "Următoarele notițe vor fi șterse (<span class=\"deleted-notes-count\"></span>)",
|
||||
"notes_to_be_deleted": "Următoarele notițe vor fi șterse ({{- noteCount}})",
|
||||
"ok": "OK",
|
||||
"to_be_deleted": " (pentru ștergere) este referențiat(ă) de relația <code>{{attrName}}</code> originând de la "
|
||||
"deleted_relation_text": "Notița {{- note}} ce va fi ștearsă este referențiată de relația {{- relation}}, originând din {{- source}}."
|
||||
},
|
||||
"delete_relation": {
|
||||
"allowed_characters": "Se permit caractere alfanumerice, underline și două puncte.",
|
||||
@ -554,7 +553,7 @@
|
||||
"open_sql_console": "Deschide consola SQL",
|
||||
"open_sql_console_history": "Deschide istoricul consolei SQL",
|
||||
"options": "Opțiuni",
|
||||
"reload_frontend": "Reîncarcă interfață",
|
||||
"reload_frontend": "Reîncarcă interfața",
|
||||
"reload_hint": "Reîncărcarea poate ajuta atunci când există ceva probleme vizuale fără a trebui repornită întreaga aplicație.",
|
||||
"reset_zoom_level": "Resetează nivelul de zoom",
|
||||
"show_backend_log": "Afișează log-ul din backend",
|
||||
@ -1439,7 +1438,8 @@
|
||||
"close_other_tabs": "Închide celelalte taburi",
|
||||
"close_tab": "Închide tab",
|
||||
"move_tab_to_new_window": "Mută acest tab în altă fereastră",
|
||||
"new_tab": "Tab nou"
|
||||
"new_tab": "Tab nou",
|
||||
"close_right_tabs": "Închide taburile din dreapta"
|
||||
},
|
||||
"toc": {
|
||||
"options": "Setări",
|
||||
|
@ -58,8 +58,16 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h
|
||||
|
||||
function getDataFileName(type: string | null, mime: string, baseFileName: string, existingFileNames: Record<string, number>): string {
|
||||
let fileName = baseFileName.trim();
|
||||
|
||||
// Crop fileName to avoid its length exceeding 30 and prevent cutting into the extension.
|
||||
if (fileName.length > 30) {
|
||||
fileName = fileName.substr(0, 30).trim();
|
||||
// We use regex to match the extension to preserve multiple dots in extensions (e.g. .tar.gz).
|
||||
let match = fileName.match(/(\.[a-zA-Z0-9_.!#-]+)$/);
|
||||
let ext = match ? match[0] : '';
|
||||
// Crop the extension if extension length exceeds 30
|
||||
const croppedExt = ext.slice(-30);
|
||||
// Crop the file name section and append the cropped extension
|
||||
fileName = fileName.slice(0, 30 - croppedExt.length) + croppedExt;
|
||||
}
|
||||
|
||||
let existingExtension = path.extname(fileName).toLowerCase();
|
||||
@ -76,6 +84,9 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h
|
||||
else if (mime === 'application/x-javascript' || mime === 'text/javascript') {
|
||||
newExtension = 'js';
|
||||
}
|
||||
else if (type === 'canvas' || mime === 'application/json') {
|
||||
newExtension = 'json';
|
||||
}
|
||||
else if (existingExtension.length > 0) { // if the page already has an extension, then we'll just keep it
|
||||
newExtension = null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user