diff --git a/package.json b/package.json
index 957ca7b29..51eedb719 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
"@excalidraw/excalidraw": "0.13.0",
"archiver": "5.3.1",
"async-mutex": "0.4.0",
- "axios": "1.2.1",
+ "axios": "1.2.2",
"better-sqlite3": "7.4.5",
"chokidar": "3.5.3",
"cls-hooked": "4.2.2",
diff --git a/src/public/app/widgets/buttons/abstract_button.js b/src/public/app/widgets/buttons/abstract_button.js
index 44be3946d..7e705d566 100644
--- a/src/public/app/widgets/buttons/abstract_button.js
+++ b/src/public/app/widgets/buttons/abstract_button.js
@@ -1,8 +1,8 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js";
-const TPL = ``;
+const TPL = ``;
export default class AbstractButtonWidget extends NoteContextAwareWidget {
isEnabled() {
@@ -22,7 +22,6 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget {
doRender() {
this.$widget = $(TPL);
- this.$iconSpan = this.$widget.find("span");
if (this.settings.onContextMenu) {
this.$widget.on("contextmenu", e => {
@@ -52,9 +51,9 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget {
}
refreshIcon() {
- for (const className of this.$iconSpan[0].classList) {
+ for (const className of this.$widget[0].classList) {
if (className.startsWith("bx-")) {
- this.$iconSpan.removeClass(className);
+ this.$widget.removeClass(className);
}
}
@@ -62,7 +61,7 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget {
? this.settings.icon()
: this.settings.icon;
- this.$iconSpan.addClass(icon);
+ this.$widget.addClass(icon);
}
initialRenderCompleteEvent() {
diff --git a/src/public/app/widgets/buttons/edit_button.js b/src/public/app/widgets/buttons/edit_button.js
index 3997b206a..dd9a7fc3b 100644
--- a/src/public/app/widgets/buttons/edit_button.js
+++ b/src/public/app/widgets/buttons/edit_button.js
@@ -39,12 +39,10 @@ export default class EditButton extends OnClickButtonWidget {
// make the edit button stand out on the first display, otherwise
// it's difficult to notice that the note is readonly
if (this.isVisible() && !wasVisible) {
- this.$iconSpan.addClass("bx-tada");
- this.$widget.css("transform", "scale(2)");
+ this.$widget.addClass("bx-tada bx-lg");
setTimeout(() => {
- this.$iconSpan.removeClass("bx-tada bx-lg");
- this.$widget.css("transform", "scale(1)");
+ this.$widget.removeClass("bx-tada bx-lg");
}, 1700);
}
}
diff --git a/src/public/app/widgets/buttons/global_menu.js b/src/public/app/widgets/buttons/global_menu.js
index 7cf669a4e..ff881aa20 100644
--- a/src/public/app/widgets/buttons/global_menu.js
+++ b/src/public/app/widgets/buttons/global_menu.js
@@ -21,12 +21,12 @@ const TPL = `
background-position: 50% 45%;
width: 100%;
height: 100%;
-
position: relative;
}
.global-menu-button:hover {
background-image: url("${window.glob.assetPath}/images/icon-color.png");
+ border: 0;
}
.global-menu-button-update-available {
diff --git a/src/services/html_sanitizer.js b/src/services/html_sanitizer.js
index 9164ddfda..c675c428a 100644
--- a/src/services/html_sanitizer.js
+++ b/src/services/html_sanitizer.js
@@ -28,7 +28,8 @@ function sanitize(dirtyHtml) {
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
'li', 'b', 'i', 'strong', 'em', 'strike', 's', 'del', 'abbr', 'code', 'hr', 'br', 'div',
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'section', 'img',
- 'figure', 'figcaption', 'span', 'label', 'input'
+ 'figure', 'figcaption', 'span', 'label', 'input',
+ 'en-media' // for ENEX import
],
allowedAttributes: {
'a': [ 'href', 'class', 'data-note-path' ],
@@ -41,6 +42,7 @@ function sanitize(dirtyHtml) {
'code': [ 'class' ],
'ul': [ 'class' ],
'table': [ 'class' ],
+ 'en-media': [ 'hash' ]
},
allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data', 'evernote'],
transformTags,
diff --git a/src/services/search/search_context.js b/src/services/search/search_context.js
index c71addb17..6c427cf5f 100644
--- a/src/services/search/search_context.js
+++ b/src/services/search/search_context.js
@@ -24,6 +24,7 @@ class SearchContext {
this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch;
this.highlightedTokens = [];
this.originalQuery = "";
+ this.fulltextQuery = ""; // complete fulltext part
// if true, becca does not have (up-to-date) information needed to process the query
// and some extra data needs to be loaded before executing
this.dbLoadNeeded = false;
diff --git a/src/services/search/search_result.js b/src/services/search/search_result.js
index 15b036e9a..4c678661d 100644
--- a/src/services/search/search_result.js
+++ b/src/services/search/search_result.js
@@ -17,18 +17,22 @@ class SearchResult {
return this.notePathArray[this.notePathArray.length - 1];
}
- computeScore(tokens) {
+ computeScore(fulltextQuery, tokens) {
this.score = 0;
+ const note = becca.notes[this.noteId];
+
+ if (note.title.toLowerCase() === fulltextQuery) {
+ this.score += 100; // high reward for exact match #3470
+ }
+
+ // notes with matches on its own note title as opposed to ancestors or descendants
+ this.addScoreForStrings(tokens, note.title, 1.5);
+
// matches in attributes don't get extra points and thus are implicitly valued less than note path matches
this.addScoreForStrings(tokens, this.notePathTitle, 1);
- // add one more time for note title alone (already contained in the notePathTitle),
- // thus preferring notes with matches on its own note title as opposed to ancestors or descendants
- const note = becca.notes[this.noteId];
- this.addScoreForStrings(tokens, note.title, 1.5);
-
if (note.isInHiddenSubtree()) {
this.score = this.score / 2;
}
diff --git a/src/services/search/services/lex.js b/src/services/search/services/lex.js
index d7a3fb83e..c3c2273eb 100644
--- a/src/services/search/services/lex.js
+++ b/src/services/search/services/lex.js
@@ -1,6 +1,7 @@
function lex(str) {
str = str.toLowerCase();
+ let fulltextQuery = "";
const fulltextTokens = [];
const expressionTokens = [];
@@ -37,6 +38,8 @@ function lex(str) {
expressionTokens.push(rec);
} else {
fulltextTokens.push(rec);
+
+ fulltextQuery = str.substr(0, endIndex + 1);
}
currentWord = '';
@@ -129,7 +132,10 @@ function lex(str) {
finishWord(str.length - 1);
+ fulltextQuery = fulltextQuery.trim();
+
return {
+ fulltextQuery,
fulltextTokens,
expressionTokens
}
diff --git a/src/services/search/services/search.js b/src/services/search/services/search.js
index 206ec63b4..3e2f5af40 100644
--- a/src/services/search/services/search.js
+++ b/src/services/search/services/search.js
@@ -170,7 +170,7 @@ function findResultsWithExpression(expression, searchContext) {
.filter(note => !!note);
for (const res of searchResults) {
- res.computeScore(searchContext.highlightedTokens);
+ res.computeScore(searchContext.fulltextQuery, searchContext.highlightedTokens);
}
if (!noteSet.sorted) {
@@ -195,7 +195,9 @@ function findResultsWithExpression(expression, searchContext) {
}
function parseQueryToExpression(query, searchContext) {
- const {fulltextTokens, expressionTokens} = lex(query);
+ const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
+ searchContext.fulltextQuery = fulltextQuery;
+
let structuredExpressionTokens;
try {
diff --git a/src/services/utils.js b/src/services/utils.js
index 8164f48e4..f243e2833 100644
--- a/src/services/utils.js
+++ b/src/services/utils.js
@@ -291,6 +291,10 @@ function deferred() {
}
function removeDiacritic(str) {
+ if (!str) {
+ return "";
+ }
+
return str.normalize("NFD").replace(/\p{Diacritic}/gu, "");
}