From 242a01e1a4b76858413b8d1d598930bb96790849 Mon Sep 17 00:00:00 2001 From: Youri Noel Nelson Date: Wed, 24 Apr 2019 15:17:48 -0400 Subject: [PATCH 1/7] Improved the Native Search Algorithm (#1) * Improved the Native Search Algorithm You can now search tags in addition to H2 and H3 titles as well as the search can now take in multiple words separated by a space. * Took out a console.log * Reflected changes to the SearchBox in the doc --- .../@vuepress/plugin-search/SearchBox.vue | 46 ++++++++++++++++--- .../docs/docs/theme/default-theme-config.md | 11 ++++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/packages/@vuepress/plugin-search/SearchBox.vue b/packages/@vuepress/plugin-search/SearchBox.vue index 6fbbd70b3e..2f6df8318f 100644 --- a/packages/@vuepress/plugin-search/SearchBox.vue +++ b/packages/@vuepress/plugin-search/SearchBox.vue @@ -64,10 +64,44 @@ export default { const { pages } = this.$site const max = SEARCH_MAX_SUGGESTIONS const localePath = this.$localePath - const matches = item => ( - item.title - && item.title.toLowerCase().indexOf(query) > -1 - ) + + const matchTest = (q, domain) => { + + const escapeRegExp = (s) => { + return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); + } + + const words = q + .split(/\s+/g) + .map(s => s.trim()) + .filter(s => !!s); + const hasTrailingSpace = q.endsWith(" "); + const searchRegex = new RegExp( + words + .map((word, i) => { + if (i + 1 === words.length && !hasTrailingSpace) { + // The last word - ok with the word being "startswith"-like + return `(?=.*\\b${escapeRegExp(word)})`; + } else { + // Not the last word - expect the whole word exactly + return `(?=.*\\b${escapeRegExp(word)}\\b)`; + } + }) + .join("") + ".+", + "gi" + ); + return searchRegex.test(domain); + } + + const matches = (item, additionalStr = null) => { + let domain; + domain = (item.title) ? item.title : ""; + domain = (item.frontmatter && item.frontmatter.tags) ? domain + " " + item.frontmatter.tags.join(" ") : domain; + if(additionalStr) domain = domain + " " + additionalStr; + + return matchTest(query, domain) + } + const res = [] for (let i = 0; i < pages.length; i++) { if (res.length >= max) break @@ -88,7 +122,7 @@ export default { for (let j = 0; j < p.headers.length; j++) { if (res.length >= max) break const h = p.headers[j] - if (matches(h)) { + if (h.title && matches(p,h.title)) { res.push(Object.assign({}, p, { path: p.path + '#' + h.slug, header: h @@ -198,7 +232,7 @@ export default { background #fff width 20rem position absolute - top 1.5rem + top 2 rem border 1px solid darken($borderColor, 10%) border-radius 6px padding 0.4rem diff --git a/packages/docs/docs/theme/default-theme-config.md b/packages/docs/docs/theme/default-theme-config.md index 9ea32bc804..c5a624c32a 100644 --- a/packages/docs/docs/theme/default-theme-config.md +++ b/packages/docs/docs/theme/default-theme-config.md @@ -327,9 +327,18 @@ search: false ``` ::: tip -Built-in Search only builds index from the title, `h2` and `h3` headers, if you need full text search, you can use [Algolia Search](#algolia-search). +Built-in Search only builds index from the title, `h2` and `h3` headers and any tags added with `YAML front matter` as shown below, if you need full text search, you can use [Algolia Search](#algolia-search). ::: +```yaml +--- +tags: + - configuration + - theme + - indexing +--- +``` + ### Algolia Search The `themeConfig.algolia` option allows you to use [Algolia DocSearch](https://community.algolia.com/docsearch/) to replace the simple built-in search. To enable it, you need to provide at least `apiKey` and `indexName`: From cfff621a93f767af2ee19f80a65d2acec30afd54 Mon Sep 17 00:00:00 2001 From: Kyle Titus Date: Fri, 6 Dec 2019 10:37:53 +0200 Subject: [PATCH 2/7] Fixed linting issues in SearchBox.vue --- .../@vuepress/plugin-search/SearchBox.vue | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/@vuepress/plugin-search/SearchBox.vue b/packages/@vuepress/plugin-search/SearchBox.vue index 3d2aaa18b5..4b9c381efe 100644 --- a/packages/@vuepress/plugin-search/SearchBox.vue +++ b/packages/@vuepress/plugin-search/SearchBox.vue @@ -78,38 +78,37 @@ export default { const localePath = this.$localePath const matchTest = (q, domain) => { - const escapeRegExp = (s) => { - return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); + return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') } const words = q .split(/\s+/g) .map(s => s.trim()) - .filter(s => !!s); - const hasTrailingSpace = q.endsWith(" "); + .filter(s => !!s) + const hasTrailingSpace = q.endsWith(' ') const searchRegex = new RegExp( words .map((word, i) => { if (i + 1 === words.length && !hasTrailingSpace) { // The last word - ok with the word being "startswith"-like - return `(?=.*\\b${escapeRegExp(word)})`; + return `(?=.*\\b${escapeRegExp(word)})` } else { // Not the last word - expect the whole word exactly - return `(?=.*\\b${escapeRegExp(word)}\\b)`; + return `(?=.*\\b${escapeRegExp(word)}\\b)` } }) - .join("") + ".+", - "gi" - ); - return searchRegex.test(domain); + .join('') + '.+', + 'gi' + ) + return searchRegex.test(domain) } const matches = (item, additionalStr = null) => { - let domain; - domain = (item.title) ? item.title : ""; - domain = (item.frontmatter && item.frontmatter.tags) ? domain + " " + item.frontmatter.tags.join(" ") : domain; - if(additionalStr) domain = domain + " " + additionalStr; + let domain + domain = (item.title) ? item.title : '' + domain = (item.frontmatter && item.frontmatter.tags) ? domain + ' ' + item.frontmatter.tags.join(' ') : domain + if (additionalStr) domain = domain + ' ' + additionalStr return matchTest(query, domain) } @@ -134,7 +133,7 @@ export default { for (let j = 0; j < p.headers.length; j++) { if (res.length >= max) break const h = p.headers[j] - if (h.title && matches(p,h.title)) { + if (h.title && matches(p, h.title)) { res.push(Object.assign({}, p, { path: p.path + '#' + h.slug, header: h From 87e3d963f582413f42203fe752d67fee2eef1479 Mon Sep 17 00:00:00 2001 From: Franck Date: Sat, 7 Mar 2020 11:47:32 +0100 Subject: [PATCH 3/7] feat: improve code readability --- .../@vuepress/plugin-search/SearchBox.vue | 42 ++---------------- .../@vuepress/plugin-search/match-query.js | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 packages/@vuepress/plugin-search/match-query.js diff --git a/packages/@vuepress/plugin-search/SearchBox.vue b/packages/@vuepress/plugin-search/SearchBox.vue index 4b9c381efe..717cfc6a6a 100644 --- a/packages/@vuepress/plugin-search/SearchBox.vue +++ b/packages/@vuepress/plugin-search/SearchBox.vue @@ -45,6 +45,8 @@