From 03370dd06639694b83eac3e000f0df0e44fdc627 Mon Sep 17 00:00:00 2001 From: Taly Date: Tue, 23 Aug 2022 14:12:15 +0300 Subject: [PATCH] add short body --- src/backend/controllers/search.ts | 68 ++++++++++++++++------ src/backend/routes/api/search.ts | 2 + src/frontend/js/modules/search.js | 15 ++++- src/frontend/styles/components/search.pcss | 14 +++++ yarn.lock | 2 +- 5 files changed, 80 insertions(+), 21 deletions(-) diff --git a/src/backend/controllers/search.ts b/src/backend/controllers/search.ts index fdb169d..af7a998 100644 --- a/src/backend/controllers/search.ts +++ b/src/backend/controllers/search.ts @@ -34,10 +34,13 @@ class Search { case 'list': blockContent = block.data.items.join(' '); break; + + default: + return; } const blockWords: string[] = blockContent - // @todo get text from inline code elements and remove html tags + .replace(/<[^>]*>?/gm, '') // lowercase all words .toLowerCase() @@ -99,36 +102,59 @@ class Search { const returnPages = pages.filter(page => foundPages.some(({ id }) => id === page._id)) .map(page => { - let shortBody = '...'; - let score = 1; + let shortBody = ''; + let flag = false; + let section = ''; + let ratio = 0; page.body.blocks.forEach((block: any) => { + if (flag) return; + let blockContent = ''; switch (block.type) { case 'header': blockContent = block.data.text; + ratio = 1; + section = blockContent; break; - // case 'paragraph': - // blockContent = block.data.text - // break; - // - // case 'list': - // blockContent = block.data.items.join(' '); - // break; + case 'paragraph': + blockContent = block.data.text + ratio = 0.5; + break; + + case 'list': + blockContent = block.data.items.join(' '); + ratio = 0.5; + break; + + default: + return; } + blockContent = blockContent + .replace(/<[^>]*>?/gm, ''); + // .toLowerCase(); + searchWords.forEach(word => { - blockContent = blockContent.replace(word, `${word}`); + // blockContent = blockContent.replace(word, `${word}`); + if (flag) return; + + if (blockContent.toLowerCase().indexOf(word) !== -1) { + + shortBody = this.highlightSubstring(blockContent, word); + flag = true; + } }) - // shortBody += blockContent; }); return { ...page, - shortBody + shortBody, + anchor: section.replace(/\s+/g, '-').toLowerCase(), + section, }; }); @@ -136,12 +162,12 @@ class Search { // --------- START test --------- - + // const uniqWords = [...new Set(pagesWords.flatMap(page => page.words))].sort(); - - uniqWords.forEach(word => { - console.log(word); - }) + // + // uniqWords.forEach(word => { + // console.log(word); + // }) // --------- END test --------- @@ -158,6 +184,12 @@ class Search { return pages; } + + private highlightSubstring(text: string, word: string) { + const wordRegExp = new RegExp(word, "ig"); + + return text.replace(wordRegExp, '$&'); + } } export default Search; diff --git a/src/backend/routes/api/search.ts b/src/backend/routes/api/search.ts index 0ece01a..aea5303 100644 --- a/src/backend/routes/api/search.ts +++ b/src/backend/routes/api/search.ts @@ -32,6 +32,8 @@ router.get('/search', async (req: Request, res: Response) => { uri: page.uri, // body: page.body, // parent: page.parent, + section: page.section, + anchor: page.anchor, shortBody: page.shortBody, }; }); diff --git a/src/frontend/js/modules/search.js b/src/frontend/js/modules/search.js index ddf9d93..21fff76 100644 --- a/src/frontend/js/modules/search.js +++ b/src/frontend/js/modules/search.js @@ -35,6 +35,7 @@ export default class Search { searchResultItem: 'search-result-item', searchResultItemTitle: 'search-result-item__title', + searchResultItemSection: 'search-result-item__section', searchResultItemDescription: 'search-result-item__description', blur: 'blurred', @@ -122,6 +123,7 @@ export default class Search { } catch (e) {} this.nodes.searchInput.focus(); + this.nodes.searchInput.select(); } createDebouncedSearch() { @@ -150,19 +152,28 @@ export default class Search { // this.nodes.searchResultWrapper.appendChild(suggestionsWrapper); data.result.pages.forEach(page => { + const url = `/${page.uri}` + (page.section ? `#${page.anchor}` : ''); + const result = document.createElement('a'); result.classList.add(this.CSS.searchResultItem); - result.setAttribute('href', `/${page.uri}`); + result.setAttribute('href', url); const title = document.createElement('div'); title.classList.add(this.CSS.searchResultItemTitle); title.innerHTML = page.title; result.appendChild(title); + if (page.section !== page.title) { + const section = document.createElement('span'); + section.classList.add(this.CSS.searchResultItemSection); + section.innerHTML = `${page.section}`; + title.appendChild(section); + } + const description = document.createElement('div'); description.classList.add(this.CSS.searchResultItemDescription); description.innerHTML = `${page.shortBody}`; - // result.appendChild(description); + result.appendChild(description); this.nodes.searchResultWrapper.appendChild(result); }); diff --git a/src/frontend/styles/components/search.pcss b/src/frontend/styles/components/search.pcss index 5a71629..835528e 100644 --- a/src/frontend/styles/components/search.pcss +++ b/src/frontend/styles/components/search.pcss @@ -83,12 +83,26 @@ font-weight: 500; } + &__section { + opacity: 0.7; + + &:before { + content: '•'; + margin: 0 5px; + text-align: center; + } + } + &__description { margin-top: 8px; + line-height: 1.5; } } } + &-word { + color: var(--color-link-active); + } } .noscroll { diff --git a/yarn.lock b/yarn.lock index d304f4c..ebd51a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4183,7 +4183,7 @@ nise@^5.1.0: node-cache@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg== dependencies: clone "2.x"