From 5f5a7880a661df9accb5a4483c18724b38535f0b Mon Sep 17 00:00:00 2001 From: bimlas Date: Mon, 19 Mar 2018 20:37:58 +0100 Subject: [PATCH 1/5] Fix tag filtering in search entry Some issues introduced in #954 (https://github.com/BoostIO/Boostnote/pull/954#issuecomment-336344915): - search by `#tag1 #tag2` returns the results of only `#tag2` - search by `#tag1 content` is as same as AND search by `#tag1 content` (and `#tag1` is regarded a word, not a tag) - search by `content #tag1` returns the results of only `#tag1` This commit fixing these: - search by `#tag1 #tag2` returns the results of only `#tag2` ![screencast](https://i.imgur.com/SjhQIhl.gif) - search by `#tag1 content` is as same as AND search by `#tag1 content` (and `#tag1` is regarded a word, not a tag) ![screencast](https://i.imgur.com/G0Tmd8c.gif) - search by `content #tag1` returns the results of only `#tag1` ![screencast](https://i.imgur.com/5MrMbE6.gif) NOTE: the examples works without `#` character too, because `findByWord()` checks the tags too. --- browser/lib/search.js | 7 ++++--- tests/lib/search-test.js | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/browser/lib/search.js b/browser/lib/search.js index dadc9a29..d0cb376c 100644 --- a/browser/lib/search.js +++ b/browser/lib/search.js @@ -4,11 +4,12 @@ export default function searchFromNotes (notes, search) { if (search.trim().length === 0) return [] const searchBlocks = search.split(' ').filter(block => { return block !== '' }) - let foundNotes = findByWord(notes, searchBlocks[0]) + let foundNotes = notes searchBlocks.forEach((block) => { - foundNotes = findByWord(foundNotes, block) if (block.match(/^#.+/)) { - foundNotes = foundNotes.concat(findByTag(notes, block)) + foundNotes = findByTag(foundNotes, block) + } else { + foundNotes = findByWord(foundNotes, block) } }) return foundNotes diff --git a/tests/lib/search-test.js b/tests/lib/search-test.js index 1550a08f..c0cbf6b7 100644 --- a/tests/lib/search-test.js +++ b/tests/lib/search-test.js @@ -20,16 +20,19 @@ test.before(t => { notes = [note1, note2, note3] }) -test('it can find notes by tags or words', t => { +test('it can find notes by tags and words', t => { // [input, expected content (Array)] const testCases = [ ['#tag1', [note1.content, note2.content, note3.content]], ['#tag1 #tag2', [note2.content]], + ['#tag2 #tag1', [note2.content]], ['#tag1 #tag2 #tag3', []], ['content1', [note1.content, note2.content]], ['content1 content2', [note2.content]], ['content1 content2 content3', []], - ['#content4', [note3.content]] + ['#content4', [note3.content]], + ['#tag2 content1', [note2.content]], + ['content1 #tag2', [note2.content]] ] testCases.forEach((testCase) => { From aae584106a6c31b038bebe3f7aab54699b7a08a3 Mon Sep 17 00:00:00 2001 From: bimlas Date: Tue, 20 Mar 2018 09:35:39 +0100 Subject: [PATCH 2/5] Look for tags in context too The previous commit broke this behaviour. Looking for a tag means the union of **tags** AND **tag in content**, so it has to search in the in currently found notes separetely, thus it has to clone the list first (`.slice(0)`). --- browser/lib/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/lib/search.js b/browser/lib/search.js index d0cb376c..13d7c736 100644 --- a/browser/lib/search.js +++ b/browser/lib/search.js @@ -7,7 +7,7 @@ export default function searchFromNotes (notes, search) { let foundNotes = notes searchBlocks.forEach((block) => { if (block.match(/^#.+/)) { - foundNotes = findByTag(foundNotes, block) + foundNotes = findByTag(foundNotes.slice(0), block).concat(findByWord(foundNotes.slice(0), block)) } else { foundNotes = findByWord(foundNotes, block) } From 4f9a0b00403630181d01ebed8ee849952e246e5b Mon Sep 17 00:00:00 2001 From: bimlas Date: Tue, 20 Mar 2018 19:01:09 +0100 Subject: [PATCH 3/5] Merge `findByTag()` and `findByWord()` into one Both looked for word in tags and content too, the only difference is when searched for `#tag`, the prefix (`#`) was truncated before compared with list of tags. --- browser/lib/search.js | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/browser/lib/search.js b/browser/lib/search.js index 13d7c736..46d47677 100644 --- a/browser/lib/search.js +++ b/browser/lib/search.js @@ -6,38 +6,28 @@ export default function searchFromNotes (notes, search) { let foundNotes = notes searchBlocks.forEach((block) => { - if (block.match(/^#.+/)) { - foundNotes = findByTag(foundNotes.slice(0), block).concat(findByWord(foundNotes.slice(0), block)) - } else { - foundNotes = findByWord(foundNotes, block) - } + foundNotes = findByWordOrTag(foundNotes, block) }) return foundNotes } -function findByTag (notes, block) { - const tag = block.match(/#(.+)/)[1] - const regExp = new RegExp(_.escapeRegExp(tag), 'i') - return notes.filter((note) => { - if (!_.isArray(note.tags)) return false - return note.tags.some((_tag) => { - return _tag.match(regExp) - }) - }) -} - -function findByWord (notes, block) { - const regExp = new RegExp(_.escapeRegExp(block), 'i') +function findByWordOrTag (notes, block) { + let tag = block + if (tag.match(/^#.+/)) { + tag = tag.match(/#(.+)/)[1] + } + const tagRegExp = new RegExp(_.escapeRegExp(tag), 'i') + const wordRegExp = new RegExp(_.escapeRegExp(block), 'i') return notes.filter((note) => { if (_.isArray(note.tags) && note.tags.some((_tag) => { - return _tag.match(regExp) + return _tag.match(tagRegExp) })) { return true } if (note.type === 'SNIPPET_NOTE') { - return note.description.match(regExp) + return note.description.match(wordRegExp) } else if (note.type === 'MARKDOWN_NOTE') { - return note.content.match(regExp) + return note.content.match(wordRegExp) } return false }) From 145ae10a793fc59651a4323c1f9a8c862c32e5c6 Mon Sep 17 00:00:00 2001 From: bimlas Date: Wed, 21 Mar 2018 20:00:02 +0100 Subject: [PATCH 4/5] Add test: find tags without hash symbol Searching has to find tags without hash symbol too (`tag` instead of `#tag`). --- tests/lib/search-test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/lib/search-test.js b/tests/lib/search-test.js index c0cbf6b7..2e288d26 100644 --- a/tests/lib/search-test.js +++ b/tests/lib/search-test.js @@ -22,7 +22,7 @@ test.before(t => { test('it can find notes by tags and words', t => { // [input, expected content (Array)] - const testCases = [ + const testWithTags = [ ['#tag1', [note1.content, note2.content, note3.content]], ['#tag1 #tag2', [note2.content]], ['#tag2 #tag1', [note2.content]], @@ -34,7 +34,11 @@ test('it can find notes by tags and words', t => { ['#tag2 content1', [note2.content]], ['content1 #tag2', [note2.content]] ] + const testWithTagsWithoutHash = testWithTags.map(function (testCase) { + return [testCase[0].replace(/#/g, ''), testCase[1]] + }) + const testCases = testWithTags.concat(testWithTagsWithoutHash) testCases.forEach((testCase) => { const [input, expectedContents] = testCase const results = searchFromNotes(notes, input) From 0d53f799b759ddb293a6e1d44c2752ed96bc0331 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 10 Apr 2018 18:40:57 +0900 Subject: [PATCH 5/5] to short an arrow function --- browser/lib/search.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/browser/lib/search.js b/browser/lib/search.js index 46d47677..b42fd389 100644 --- a/browser/lib/search.js +++ b/browser/lib/search.js @@ -19,9 +19,7 @@ function findByWordOrTag (notes, block) { const tagRegExp = new RegExp(_.escapeRegExp(tag), 'i') const wordRegExp = new RegExp(_.escapeRegExp(block), 'i') return notes.filter((note) => { - if (_.isArray(note.tags) && note.tags.some((_tag) => { - return _tag.match(tagRegExp) - })) { + if (_.isArray(note.tags) && note.tags.some((_tag) => _tag.match(tagRegExp))) { return true } if (note.type === 'SNIPPET_NOTE') {