Conversation
src/index.js
Outdated
| tipBox, | ||
| tooltip, | ||
| pic, | ||
| searchbar, |
There was a problem hiding this comment.
While @acjh mentioned in the earlier PR to move above trigger, I think it should be moved above select instead, because pic is in the wrong alphabetical order.
src/Typeahead.vue
Outdated
| filters: { | ||
| highlight (value, phrase) { | ||
| return value.replace(new RegExp('(' + phrase + ')', 'gi'), '<strong>$1</strong>') | ||
| return value.replace(new RegExp('(' + phrase + ')', 'gi'), '<mark>$1</mark>') |
There was a problem hiding this comment.
Is it possible to override filters methods in vue? I think @acjh didn't want the method to be modified for Typeahead, so should consider overriding this method in searchbar instead if possible.
|
Can you rebase this on |
|
sure, I'm doing it now. |
c487447 to
e5603bb
Compare
docs/bodyDocs.vue
Outdated
| import searchbarDocs from './example/searchbarDocs.vue' | ||
| import tipBoxDocs from './example/tipBoxDocs.vue' | ||
| import triggerDocs from './example/triggerDocs.vue' | ||
| import TypeaheadDocs from './example/typeaheadDocs.vue'; |
There was a problem hiding this comment.
Shouldn't use capital letters for TypeaheadDocs, should be typeaheadDocs.
docs/bodyDocs.vue
Outdated
|
|
||
| export default { | ||
| components: { | ||
| TypeaheadDocs, |
There was a problem hiding this comment.
You can move it below tooltipDocs.
| } | ||
| </doc-code> | ||
| <!-- eslint-disable --> | ||
| </doc-section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| <template> | ||
| <doc-section | ||
| id="searchbar" | ||
| name="searchbar"> |
There was a problem hiding this comment.
I don't find this ideal 😕, so I think we will need to fix eslint.
Can you help us modify .eslintrc.js on your branch to add in the following lines shown below as a separate commit. Then you can put all the attributes on one line instead of having to split to one attribute each line (e.g. <doc-section id="searchbar" name="searchbar">)
diff --git a/.eslintrc.js b/.eslintrc.js
index b74d1ab1..305ef01b 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -21,5 +21,15 @@ module.exports = {
'operator-linebreak': ['error', 'before'],
'quote-props': 'off',
'vue/order-in-components': 'off',
+ 'vue/max-attributes-per-line': [
+ {
+ 'singleline': 5,
+ 'multiline':
+ {
+ 'max': 5,
+ 'allowFirstLine': false,
+ },
+ },
+ ],
},
};There was a problem hiding this comment.
id should be searchbarDocs, name should be Searchbar.
docs/example/searchbarDocs.vue
Outdated
| } | ||
| } | ||
| </doc-code> | ||
| <!-- eslint-disable --> |
There was a problem hiding this comment.
Should be <!-- eslint-enable -->
docs/example/searchbarDocs.vue
Outdated
| <template> | ||
| <doc-section | ||
| id="searchbar" | ||
| name="searchbar"> |
There was a problem hiding this comment.
id should be searchbarDocs, name should be Searchbar.
|
|
||
| <script> | ||
| // eslint-disable-next-line import/no-unresolved | ||
| import searchbar from 'src/Searchbar.vue'; |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| import searchbar from 'src/Searchbar.vue'; | ||
| import docCode from './docCode.vue'; | ||
| import docSection from './docSection.vue'; | ||
|
|
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| export default { | ||
| components: { | ||
| docCode, | ||
| docSection, |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| 'title': '', | ||
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value" /><br />' |
There was a problem hiding this comment.
-
Let's do
<span></span>as it's not a proper empty element:
-
Let's modify the relevant rule:
'vue/html-self-closing': [ 'error', { 'html': { 'void': 'always', 'normal': 'never', }, }, ],
docs/example/searchbarDocs.vue
Outdated
| template-name="search" | ||
| /> | ||
| </doc-code> | ||
| <!-- eslint-disable --> |
There was a problem hiding this comment.
Let's disable specific rules, and do it inside <doc-code>:
<doc-code language="javascript">
<!-- eslint-disable vue/html-indent, vue/no-parsing-error, vue/valid-v-html -->
new Vue {
...
}
<!-- eslint-enable vue/html-indent, vue/no-parsing-error, vue/valid-v-html -->
</doc-code>There was a problem hiding this comment.
You need to remove this <!-- eslint-disable --> after adding the one inside. :P
src/index.js
Outdated
| tipBox, | ||
| tooltip, | ||
| pic, | ||
| searchbar, |
src/searchbar.vue
Outdated
| overflow: scroll; | ||
| overflow-x: hidden; | ||
| } | ||
| </style> No newline at end of file |
src/searchbar.vue
Outdated
| .search-dropdown-menu { | ||
| height: 30em; | ||
| overflow: scroll; | ||
| overflow-x: hidden; |
There was a problem hiding this comment.
- overflow: scroll;
overflow-x: hidden;
+ overflow-y: scroll;
docs/example/searchbarDocs.vue
Outdated
| <template> | ||
| <doc-section | ||
| id="searchbarDocs" | ||
| name="searchbar"> |
There was a problem hiding this comment.
-
As @yamgent suggested, let's modify .eslintrc.js (it should be committed):
'vue/max-attributes-per-line': [ 'error', { 'singleline': 2, 'multiline': { 'max': 1, 'allowFirstLine': false, }, }, ],
Let's keep it strict.
-
Capitalize
Sinname="searchbar":<doc-section id="searchbarDocs" name="Searchbar">
There was a problem hiding this comment.
Capitalize S in name="searchbar"
Because it's used in sidebar and heading.
docs/example/searchbarDocs.vue
Outdated
| template-name="search" | ||
| /> | ||
| </doc-code> | ||
| <!-- eslint-disable --> |
There was a problem hiding this comment.
You need to remove this <!-- eslint-disable --> after adding the one inside. :P
src/index.js
Outdated
| tipBox, | ||
| tooltip, | ||
| pic, | ||
| searchbar, |
| popoverDocs, | ||
| retrieverDocs, | ||
| selectDocs, | ||
| searchbarDocs, |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
.eslintrc.js
Outdated
| { | ||
| 'singleline': 2, | ||
| 'multiline': { | ||
| 'max': 2, |
There was a problem hiding this comment.
Why 'max': 2? Let's not modify 'multiline':
'vue/max-attributes-per-line': ['error', { 'singleline': 2 }],
docs/example/searchbarDocs.vue
Outdated
| <div> | ||
| <p>template</p> | ||
| <p><code>String</code></p> | ||
| <p><code><span v-html="$value | highlight query"></span></code></p> |
| <p><code><span v-html="$value | highlight query"></span></code></p> | ||
| <p>Used to render suggestion.</p> | ||
| </div> | ||
| </doc-table> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| </div> | ||
| </doc-table> | ||
| </doc-section> | ||
|
|
|
|
||
| <script> | ||
| // eslint-disable-next-line import/no-unresolved | ||
| import searchbar from 'src/Searchbar.vue'; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| import docSection from './docSection.vue'; | ||
| import docTable from './docTable.vue'; | ||
|
|
||
|
|
| 'feature-list': 'Feature list', | ||
| }, | ||
| 'title': 'Hello World', | ||
| 'src': 'index.md', |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value"></span>><br />' | ||
| + '<span v-if="item.keywords" v-html="item.keywords | highlightAndExtract value <br />"></span>' |
There was a problem hiding this comment.
- Extra
>in</span>>. - Standardize
<br />after span. - Can we do
"item.keywords | extract value | highlight value"for code reuse and consistency?
There was a problem hiding this comment.
this part need to be changed if we want inconsecutive keywords match.May I change it in that PR
| <p>The local data source for suggestions. Expected to be a primitive array.</p> | ||
| </div> | ||
| <div> | ||
| <p>on-hit</p> |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
.eslintrc.js
Outdated
| 'allowFirstLine': false, | ||
| }, | ||
| }, | ||
| ], |
There was a problem hiding this comment.
Let's not modify
'multiline':'vue/max-attributes-per-line': ['error', { 'singleline': 2 }],
There was a problem hiding this comment.
@nusjzx reminder. Some of the comments are yet to be resolved as well.
| 'feature-list': 'Feature list', | ||
| }, | ||
| 'title': 'Hello World', | ||
| 'src': 'index.md', |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| <p>template-name</p> | ||
| <p><code>String</code></p> | ||
| <p></p> | ||
| <p>Used to specify name of the template</p> |
docs/example/searchbarDocs.vue
Outdated
| </div> | ||
| </doc-table> | ||
| </doc-section> | ||
|
|
src/searchbar.vue
Outdated
|
|
||
| return matches; | ||
| } | ||
| return {}; |
There was a problem hiding this comment.
Refactoring primitiveData().
Iteration 1:
- Early
return. - Rename
valuetoentryas there'sthis.value. - Rename
querytoregexas there'sthis.query. - Reorder destructuring of
entryalphabetically. - Reorder
constbeforelet. - Remove unnecessary
if (Object.keys(headings).length !== 0). - Use
regex.test(text)instead oftext.search(query) !== -1. - Reorder properties of object in
matches.push(object)alphabetically. - Replaced
words.search(query) !== -1withregex.test(title) || regex.test(keywords).
if (!this.data) {
return {};
}
const matches = [];
this.data.forEach((entry) => {
const { headings, src, title } = entry;
const keywords = entry.keywords || '';
const regex = new RegExp(this.value, 'i');
let hasMatchingHeading = false;
Object.entries(headings).forEach(([id, text]) => {
if (regex.test(text)) {
hasMatchingHeading = true;
matches.push({
heading: { id, text },
keywords,
src,
title,
});
}
});
if (!hasMatchingHeading) {
if (regex.test(title) || regex.test(keywords)) {
matches.push(entry);
}
}
});
return matches;Now trying Array.prototype.reduce().
There was a problem hiding this comment.
Iteration 2:
- Return early with
undefined. - Assign
regexoutsideforEach.
if (!this.data) {
return undefined;
}
const matches = [];
const regex = new RegExp(this.value, 'i');
this.data.forEach((entry) => {
const { headings, src, title } = entry;
const keywords = entry.keywords || '';
let hasMatchingHeading = false;
Object.entries(headings).forEach(([id, text]) => {
if (regex.test(text)) {
hasMatchingHeading = true;
matches.push({
heading: { id, text },
keywords,
src,
title,
});
}
});
if (!hasMatchingHeading) {
if (regex.test(title) || regex.test(keywords)) {
matches.push(entry);
}
}
});
return matches;There was a problem hiding this comment.
An attempt at reduce that's less appealing:
if (!this.data) {
return undefined;
}
const regex = new RegExp(this.value, 'i');
return this.data.reduce((matches, entry) => {
const { headings, src, title } = entry;
const keywords = entry.keywords || '';
const headingMatches = Object.entries(headings).reduce((acc, [id, text]) => {
if (regex.test(text)) {
acc.push({
heading: { id, text },
keywords,
src,
title,
});
}
return acc;
}, []);
if (headingMatches.length) {
return matches.concat(headingMatches);
}
if (regex.test(title) || regex.test(keywords)) {
matches.push(entry);
}
return matches;
}, []);| 'src': 'bugs/index.md', | ||
| 'title': 'Open Bugs', | ||
| }, | ||
| { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
yamgent
left a comment
There was a problem hiding this comment.
Nice job. Just one minor nit left, then I think we are good to go. 👍
src/searchbar.vue
Outdated
| highlightAndExtract(value, phrase) { | ||
| const words = value.split(',').map(word => word.trim()); | ||
| return words.reduce((pre, next) => { | ||
| const regex = new RegExp(`(${phrase})`, 'gi'); |
There was a problem hiding this comment.
You can move the regex constant out of the reduce method, like so:
highlightAndExtract(value, phrase) {
const regex = new RegExp(`(${phrase})`, 'gi');
const words = value.split(',').map(word => word.trim());
return words.reduce((pre, next) => {
const isMatch = next.match(regex);
return pre + (isMatch ? `${next.replace(regex, '<mark>$1</mark>')} ` : '');
}, '');
},| 'feature-list': 'Feature list', | ||
| }, | ||
| 'title': 'Hello World', | ||
| 'src': 'index.md', |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
src/index.js
Outdated
| tipBox, | ||
| tooltip, | ||
| pic, | ||
| searchbar, |
docs/example/searchbarDocs.vue
Outdated
| 'title': '', | ||
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value"></span><br />' |
docs/example/searchbarDocs.vue
Outdated
| defaultCallback(items) { | ||
| console.log(items); | ||
| } | ||
| } |
There was a problem hiding this comment.
- Fix eslint errors and warnings.
- Should be singular
item. - Let's rename it
consoleCallbackas it's not a default.
There was a problem hiding this comment.
eslint doesn't allow console.log()
There was a problem hiding this comment.
I will change it to other callback
There was a problem hiding this comment.
Unless you have a better idea:
// eslint-disable-next-line no-console
docs/example/searchbarDocs.vue
Outdated
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value <br />"></span>' | ||
| + '<span v-if="item.keywords" v-html="item.keywords | highlightAndExtract value <br />"></span>' |
There was a problem hiding this comment.
From #30 (comment):
- Can we do
"item.keywords | extract value | highlight value"for code reuse and consistency?this part need to be changed if we want inconsecutive keywords match.May I change it in that PR
No, we shouldn't compromise this PR.
e22092e to
5ec7d21
Compare
docs/example/searchbarDocs.vue
Outdated
| 'title': '', | ||
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value"></span>' |
There was a problem hiding this comment.
@acjh Should we just consider using this value as the default? I think the logic in searchbar now assumes that the structure of item will always include title, keywords and a list of heading. Seems to be reasonable to give the user a default search template in that case.
There was a problem hiding this comment.
Good point, especially if we would be using the same. Let's do that.
-
Let's have a more realistic
consoleCallback, which shows the use of.srcand.heading.id:consoleCallback(match) { const page = `/${match.src.replace('.md', '.html')}`; const anchor = match.heading ? `#${match.heading.id}` : ''; console.log(`${page}${anchor}`); },
-
Should
keywordsandheadingbe<small>instead of<span>?
So thattitlestands out, rather than just three lines of words.
src/searchbar.vue
Outdated
| highlight(value, phrase) { | ||
| return value.replace(new RegExp(`(${phrase})`, 'gi'), '<mark>$1</mark>'); | ||
| }, | ||
| extract(value, phrase) { |
There was a problem hiding this comment.
Can consider removing this method since it is no longer used.
docs/example/searchbarDocs.vue
Outdated
| 'title': '', | ||
| }, | ||
| ], | ||
| searchTemplate: '<span v-html="item.title | highlight value"></span>' |
There was a problem hiding this comment.
Good point, especially if we would be using the same. Let's do that.
-
Let's have a more realistic
consoleCallback, which shows the use of.srcand.heading.id:consoleCallback(match) { const page = `/${match.src.replace('.md', '.html')}`; const anchor = match.heading ? `#${match.heading.id}` : ''; console.log(`${page}${anchor}`); },
-
Should
keywordsandheadingbe<small>instead of<span>?
So thattitlestands out, rather than just three lines of words.
docs/example/searchbarDocs.vue
Outdated
| 'keywords': 'k1, k2, k3', | ||
| 'src': 'index.md', | ||
| 'title': 'Hello World', | ||
|
|
There was a problem hiding this comment.
Remove empty line (to be consistent with code).
docs/example/searchbarDocs.vue
Outdated
| { | ||
| 'headings': { | ||
| 'popover-initiated-by-trigger-honor-trigger-attribute': | ||
| 'popover initiated by trigger: honor trigger attribute', |
There was a problem hiding this comment.
Indent by 2 spaces (to be consistent with code).
docs/example/searchbarDocs.vue
Outdated
| methods: { | ||
| consoleCallback(item) { | ||
| console.log(item); | ||
| } |
There was a problem hiding this comment.
Missing comma (to be consistent with code).
src/index.js
Outdated
| @@ -49,7 +51,7 @@ const components = { | |||
| tooltip, | |||
| pic, | |||
There was a problem hiding this comment.
Since you reordered the import statements, let's reorder these as well.
docs/example/searchbarDocs.vue
Outdated
| <doc-code language="markup"> | ||
| <searchbar | ||
| :data="searchData" | ||
| :template="searchTemplate" |
There was a problem hiding this comment.
Add :on-hit (to be consistent with code).
docs/example/searchbarDocs.vue
Outdated
| }, | ||
| 'keywords': 'k7, k8, k9', | ||
| 'src': 'sub_site/index.md', | ||
| 'title': '', |
There was a problem hiding this comment.
We expect title to not be empty, since we don't use v-if.
| consoleCallback(match) { | ||
| const page = `/${match.src.replace('.md', '.html')}`; | ||
| const anchor = match.heading ? `#${match.heading.id}` : ''; | ||
| console.log(`${page}${anchor}`); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| + '<br v-if="item.keywords" />' | ||
| + '<span v-if="item.keywords" v-html="item.keywords | highlight value"></span>' | ||
| + '<br v-if="item.heading" />' | ||
| + '<span v-if="item.heading" v-html="item.heading.text | highlight value"></span>', |
src/searchbar.vue
Outdated
| + '<br v-if="item.keywords" />' | ||
| + '<span v-if="item.keywords" v-html="item.keywords | highlight value"></span>' | ||
| + '<br v-if="item.heading" />' | ||
| + '<span v-if="item.heading" v-html="item.heading.text | highlight value"></span>', |
There was a problem hiding this comment.
From #30 (comment):
- Should
keywordsandheadingbe<small>instead of<span>?
So thattitlestands out, rather than just three lines of words.
src/searchbar.vue
Outdated
| highlight(value, phrase) { | ||
| return value.replace(new RegExp(`(${phrase})`, 'gi'), '<mark>$1</mark>'); | ||
| }, | ||
| extract(value, phrase) { |
docs/example/searchbarDocs.vue
Outdated
| <div> | ||
| <p>template</p> | ||
| <p><code>String</code></p> | ||
| <p><code><span v-html="$value | highlight query"></span></code></p> |
There was a problem hiding this comment.
This should be updated. Perhaps:
<div>
<p>template</p>
<p><code>String</code></p>
<p>See below.</p>
<p>Used to render suggestion.</p>
</div>
<div>
<p>template-name</p>
<p><code>String</code></p>
<p></p>
<p>Used to specify name of the template.</p>
</div>
</doc-table>
Default template:
<doc-code>
<span v-html="item.title | highlight value"></span>
<br v-if="item.keywords" />
<span v-if="item.keywords" v-html="item.keywords | highlight value"></span>
<br v-if="item.heading" />
<span v-if="item.heading" v-html="item.heading.text | highlight value"></span>
</doc-code>
docs/example/searchbarDocs.vue
Outdated
| <doc-code> | ||
| <span v-html="item.title | highlight value"></span> | ||
| <br v-if="item.keywords" /> | ||
| <span v-if="item.keywords" v-html="item.keywords | highlight value"></span> |
| </doc-table> | ||
| Default template: | ||
| <doc-code> | ||
| <span v-html="item.title | highlight value"></span> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| <div> | ||
| <p>template</p> | ||
| <p><code>String</code></p> | ||
| <p><code>See below.</code></p> |
docs/example/searchbarDocs.vue
Outdated
| <p></p> | ||
| <p>Used to specify name of the template.</p> | ||
| </div> | ||
| <!-- eslint-disable vue/no-parsing-error, vue/valid-v-html --> |
There was a problem hiding this comment.
- I commented on Line 97, not Line 94.
- Remember the corresponding
eslint-enable.
|
Looks fine now. Please squash the commits. |
|
Just a query: What is the purpose of |
|
It's used to register a partial: Lines 35 to 38 in eacf092 |
5daa5c2 to
bf88b1d
Compare
|
Nice job squashing the commits, the commit message title can be improved as follows:
|
bf88b1d to
d415696
Compare
src/Typeahead.vue
Outdated
| @blur="showDropdown = false" | ||
| /> | ||
| <ul class="dropdown-menu" v-el:dropdown> | ||
| <ul class="dropdown-menu search-dropdown-menu" v-el:dropdown> |
There was a problem hiding this comment.
Instead of modifying Typeahead.vue, let's add this in Searchbar.vue:
mounted() {
this.$els.dropdown.classList.add('search-dropdown-menu');
},You can add it between extends and partials.
src/searchbar.vue
Outdated
| @@ -0,0 +1,57 @@ | |||
| <script> | |||
| import Typeahead from './Typeahead.vue'; | |||
There was a problem hiding this comment.
-
Lowercase for imported variable:
import typeahead from './Typeahead.vue';
-
Uppercase for the name of this file: Searchbar.vue
There was a problem hiding this comment.
but all other files in that folder is lowercase.
There was a problem hiding this comment.
There was a problem hiding this comment.
oops, I was looking at the docs files...
| <doc-code> | ||
| <!-- eslint-disable vue/no-parsing-error, vue/valid-v-html --> | ||
| <span v-html="item.title | highlight value"></span> | ||
| <br v-if="item.keywords" /> |
There was a problem hiding this comment.
@acjh The alternative is to not render it as a HTML snippet, but I think that's a bit extreme just to fix a missing slash. I suggest we just live with the flaw? :P
| 'src': 'sub_site/index.md', | ||
| 'title': 'Feature Page', | ||
| }, | ||
| ], |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
docs/example/searchbarDocs.vue
Outdated
| docTable, | ||
| searchbar, | ||
| }, | ||
| partials: {}, |
|
Nope. Squash commits and can merge. |
|
Publish this (and update) before merging the MarkBind one. |
cf63641 to
65c41f0
Compare




What is the purpose of this pull request? (put "X" next to an item, remove the rest)
• [] Documentation update
• [ ] Bug fix
• [ ] New feature
• [x] Enhancement to an existing feature
• [ ] Other, please explain:
Related MarkBind/markbind#162, MarkBind/markbind#204
What is the rationale for this request?
highlighting and extracting the search result helps users to identify the results they want easily,
searching for headings and jump to the headings on click helpers users to go to website sections easily.
What changes did you make? (Give an overview)
highlightAndExtract function will extract the matching results then highlight the phrases.
for jumping to a specific heading, we have one entry for each heading(suggested by Prof Damith).
Thus, Instead of processing on a single string that combines title, keywords and headings, we match headings first, then title and keywords.
Testing instructions:
in vue-strap npm run build
copy paste vue-strap.min.js to markbind
After cloning the CS3281 website, go to common/header.md, and replace the use of typeahead with searchbar
test on 3281 website