diff --git a/db/migrations/0212__delete_all_attributes_of_named_notes.js b/db/migrations/0212__delete_all_attributes_of_named_notes.js index 47ddb9114..d90f25e44 100644 --- a/db/migrations/0212__delete_all_attributes_of_named_notes.js +++ b/db/migrations/0212__delete_all_attributes_of_named_notes.js @@ -2,12 +2,18 @@ module.exports = () => { const cls = require("../../src/services/cls"); const beccaLoader = require("../../src/becca/becca_loader"); const becca = require("../../src/becca/becca"); + const log = require("../../src/services/log"); cls.init(() => { beccaLoader.load(); const hidden = becca.getNote("_hidden"); + if (!hidden) { + log.info("MIGRATION 212: no _hidden note, skipping."); + return; + } + for (const noteId of hidden.getSubtreeNoteIds({includeHidden: true})) { if (noteId.startsWith("_")) { // is "named" note const note = becca.getNote(noteId); diff --git a/package-lock.json b/package-lock.json index dbd019d3b..8117a4a56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,11 @@ { "name": "trilium", - "version": "0.59.1", + "version": "0.59.2", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "trilium", - "version": "0.59.1", + "version": "0.59.2", "hasInstallScript": true, "license": "AGPL-3.0-only", "dependencies": { diff --git a/package.json b/package.json index 05baeaf2f..5d7c9d49b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "trilium", "productName": "Trilium Notes", "description": "Trilium Notes", - "version": "0.59.1", + "version": "0.59.2", "license": "AGPL-3.0-only", "main": "electron.js", "bin": { diff --git a/src/becca/becca_loader.js b/src/becca/becca_loader.js index ad4c90a10..f7659e964 100644 --- a/src/becca/becca_loader.js +++ b/src/becca/becca_loader.js @@ -70,7 +70,9 @@ function reload() { } function postProcessEntityUpdate(entityName, entity) { - if (entityName === 'branches') { + if (entityName === 'notes') { + noteUpdated(entity); + } else if (entityName === 'branches') { branchUpdated(entity); } else if (entityName === 'attributes') { attributeUpdated(entity); @@ -161,6 +163,15 @@ function branchDeleted(branchId) { delete becca.branches[branch.branchId]; } +function noteUpdated(entity) { + const note = becca.notes[entity.noteId]; + + if (note) { + // type / mime could have been changed, and they are present in flatTextCache + note.flatTextCache = null; + } +} + function branchUpdated(branch) { const childNote = becca.notes[branch.noteId]; diff --git a/src/public/app/entities/fnote.js b/src/public/app/entities/fnote.js index 1f44a97bf..70594d647 100644 --- a/src/public/app/entities/fnote.js +++ b/src/public/app/entities/fnote.js @@ -706,7 +706,14 @@ class FNote { }); // attrs are not resorted if position changes after initial load - promotedAttrs.sort((a, b) => a.position < b.position ? -1 : 1); + promotedAttrs.sort((a, b) => { + if (a.noteId === b.noteId) { + return a.position < b.position ? -1 : 1; + } else { + // inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761 + return a.noteId < b.noteId ? -1 : 1; + } + }); return promotedAttrs; } diff --git a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js index e434c20a6..01031686e 100644 --- a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js +++ b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js @@ -92,7 +92,18 @@ export default class InheritedAttributesWidget extends NoteContextAwareWidget { } getInheritedAttributes(note) { - return note.getAttributes().filter(attr => attr.noteId !== this.noteId); + const attrs = note.getAttributes().filter(attr => attr.noteId !== this.noteId); + + attrs.sort((a, b) => { + if (a.noteId === b.noteId) { + return a.position < b.position ? -1 : 1; + } else { + // inherited attributes should stay grouped: https://github.com/zadam/trilium/issues/3761 + return a.noteId < b.noteId ? -1 : 1; + } + }); + + return attrs; } entitiesReloadedEvent({loadResults}) { diff --git a/src/public/app/widgets/sql_result.js b/src/public/app/widgets/sql_result.js index 142dc79e3..4224e714b 100644 --- a/src/public/app/widgets/sql_result.js +++ b/src/public/app/widgets/sql_result.js @@ -60,7 +60,7 @@ export default class SqlResultWidget extends NoteContextAwareWidget { const $row = $(""); for (const key in result) { - $row.append($("").html(key)); + $row.append($("").text(key)); } $table.append($row); @@ -69,7 +69,7 @@ export default class SqlResultWidget extends NoteContextAwareWidget { const $row = $(""); for (const key in result) { - $row.append($("").html(result[key])); + $row.append($("").text(result[key])); } $table.append($row); diff --git a/src/services/build.js b/src/services/build.js index cd5327164..8b4a403e6 100644 --- a/src/services/build.js +++ b/src/services/build.js @@ -1 +1 @@ -module.exports = { buildDate:"2023-02-28T23:39:34+01:00", buildRevision: "9eb3075f65af98bd8c4a8ca8cc241ae2ae05bfa9" }; +module.exports = { buildDate:"2023-03-14T21:15:08+01:00", buildRevision: "d8e9086bdeb721db795783b5d92395a9bd6882c9" }; diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 3fecf607c..dc2e6072c 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -156,7 +156,7 @@ class ConsistencyChecks { let message = `Branch '${branchId}' was was missing parent note '${parentNoteId}', so it was deleted. `; if (becca.getNote(noteId).getParentBranches().length === 0) { - const newBranch = new Branch({ + const newBranch = new BBranch({ parentNoteId: 'root', noteId: noteId, prefix: 'recovered' @@ -447,7 +447,7 @@ class ConsistencyChecks { branch.markAsDeleted("parent-is-search"); // create a replacement branch in root parent - new Branch({ + new BBranch({ parentNoteId: 'root', noteId: branch.noteId, prefix: 'recovered' diff --git a/src/services/search/services/search.js b/src/services/search/services/search.js index 80b49f3bb..4b4f2110e 100644 --- a/src/services/search/services/search.js +++ b/src/services/search/services/search.js @@ -299,7 +299,9 @@ function highlightSearchResults(searchResults, highlightedTokens) { // which would make the resulting HTML string invalid. // { and } are used for marking and tag (to avoid matches on single 'b' character) // < and > are used for marking and - highlightedTokens = highlightedTokens.map(token => token.replace('/[<\{\}]/g', '')); + highlightedTokens = highlightedTokens + .map(token => token.replace('/[<\{\}]/g', '')) + .filter(token => !!token?.trim()); // sort by the longest, so we first highlight the longest matches highlightedTokens.sort((a, b) => a.length > b.length ? -1 : 1); @@ -307,7 +309,7 @@ function highlightSearchResults(searchResults, highlightedTokens) { for (const result of searchResults) { const note = becca.notes[result.noteId]; - result.highlightedNotePathTitle = result.notePathTitle.replace('/[<\{\}]/g', ''); + result.highlightedNotePathTitle = result.notePathTitle.replace(/[<{}]/g, ''); if (highlightedTokens.find(token => note.type.includes(token))) { result.highlightedNotePathTitle += ` "type: ${note.type}'`;