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"