22 <section v-if =" data.length" class =" drawer-main__search-results" >
33 <template v-for =" (item , index ) in visibleResults " :key =" item .objectID || index " >
44 <div class =" search-result" @click =" gotTo(parseUrl(item.url))" >
5- <div class =" search-result__title" v-html =" getTitleForArticle(item.title)" ></div >
6- <div class =" search-result__breadcrumb" v-html =" getBreadcrumbsForArticle(item.title)" ></div >
7- <div class =" search-result__text" v-html =" formatPreviewMarkdown(item.preview)" ></div >
5+ <div
6+ class =" search-result__title"
7+ v-html =" highlightMatchingWords(getTitleForArticle(item.title), modelValue)"
8+ ></div >
9+ <div
10+ class =" search-result__breadcrumb"
11+ v-html =" highlightMatchingWords(getBreadcrumbsForArticle(item.title), modelValue)"
12+ ></div >
13+ <div
14+ class =" search-result__text"
15+ v-html =" highlightMatchingWords(formatPreviewMarkdown(item.preview), modelValue)"
16+ ></div >
817 </div >
918 </template >
1019 <div v-if =" countOfHiddenResults > 0" class =" show-more" @click =" showAllHiddenResult" >
1120 <p >Show {{ countOfHiddenResults }} more results</p >
1221 </div >
1322 </section >
1423 <div v-else >
15- <p v-if =" !modelValue.length" class =" no_results" >Write your search query, then press Enter or click the search button.</p >
24+ <p v-if =" !modelValue.length" class =" no_results" >Please type your search query, then press Enter or click the search button.</p >
1625 </div >
1726</template >
1827
@@ -23,10 +32,7 @@ import { marked } from "marked";
2332const renderer = new marked.Renderer ();
2433
2534renderer .heading = function (text ) {
26- // check if text is a string
27- if (typeof text !== " string" ) {
28- return " " ;
29- }
35+ if (typeof text !== " string" ) return " " ;
3036 return ` <strong>${ text} </strong>` ;
3137};
3238
@@ -36,8 +42,7 @@ renderer.image = function () {
3642
3743const formatPreviewMarkdown = (markdown ) => {
3844 let md = marked (markdown, { renderer });
39- // remove all <br> tags
40- md = md .replace (/ <br>/ g , " " );
45+ md = md .replace (/ <br>/ g , " " ); // Remove all <br> tags
4146 return md;
4247};
4348
@@ -52,24 +57,20 @@ const props = defineProps({
5257 },
5358});
5459
55- const { MAX_VISIBLE_RESULT } = inject (' themeConfig' );
60+ const { MAX_VISIBLE_RESULT } = inject (" themeConfig" );
5661const isShowAllResult = ref (false );
5762
5863const gotTo = (url ) => {
59- let parsedCurrentUrl = new URL (window .location .href );
60- let parsedCurrentUrlBase = parsedCurrentUrl .origin ;
61- let parsedCurrentUrlHash = parsedCurrentUrl .hash ;
62- let parsedCurrentUrlPathname = parsedCurrentUrl .pathname ;
63-
64- if (parsedCurrentUrlPathname + parsedCurrentUrlHash === url) {
64+ const parsedCurrentUrl = new URL (window .location .href );
65+ if (parsedCurrentUrl .pathname + parsedCurrentUrl .hash === url) {
6566 window .location .reload ();
6667 return ;
6768 }
68- window .location .href = parsedCurrentUrlBase + url;
69+ window .location .href = parsedCurrentUrl . origin + url;
6970};
7071
7172const parseUrl = (url ) => {
72- let parsed = new URL (url);
73+ const parsed = new URL (url);
7374 return parsed .pathname + parsed .hash ;
7475};
7576
@@ -93,19 +94,28 @@ const getTitleForArticle = (title) => {
9394const getBreadcrumbsForArticle = (title ) => {
9495 let sliced = title .split (" ->" ).map ((part ) => part .trim ());
9596 sliced .pop ();
96- return sliced .join (' > ' );
97+ return sliced .join (" > " );
9798};
9899
100+ // Function to highlight matching words
101+ const highlightMatchingWords = (text , query ) => {
102+ if (! query .trim ()) return text; // If the query is empty, return the text as is
103+
104+ const regex = new RegExp (` (${ query .split (/ \s + / ).join (" |" )} )` , " gi" );
105+ return text .replace (regex, " <mark>$1</mark>" );
106+ };
99107< / script>
100108
101109< style lang= " stylus" >
102110@import " ../../styles/config.styl" ;
103111
104112.drawer - main__search- results {
105113 display: grid;
106- grid- template- columns: repeat (auto- fill, minmax (280px , 1fr )); // Flexible grid with min width
107- gap: 1 .5rem ; // Increased gap for better spacing
108- padding: 1rem ; // Padding around the results area
114+ grid- template- columns: repeat (3 , 1fr ); // Ensures exactly 3 columns on desktop
115+ gap: 1 .2rem ;
116+ padding: 0 .5rem ; // Padding around the results area
117+ width: 80vw ;
118+ margin: 0 auto;
109119}
110120
111121.search - result {
@@ -143,7 +153,7 @@ const getBreadcrumbsForArticle = (title) => {
143153 overflow: hidden;
144154 display: - webkit- box;
145155 - webkit- box- orient: vertical;
146- - webkit- line- clamp: 3 ; // Limit preview text lines for coherence
156+ - webkit- line- clamp: 5 ; // Limit preview text lines for coherence
147157 - webkit- box- decoration- break: clone;
148158 box- decoration- break: clone;
149159 }
@@ -152,6 +162,8 @@ const getBreadcrumbsForArticle = (title) => {
152162 font- size: $drawerSearchResultBreadcrumbTextSize;
153163 color: $drawerSearchResultBreadcrumbColor;
154164 margin: 0 ;
165+ line- height: 1.4 ;
166+ margin- top: 0 .5rem ;
155167 }
156168}
157169
@@ -180,4 +192,10 @@ const getBreadcrumbsForArticle = (title) => {
180192 font- size: 1 .25rem ;
181193 }
182194}
183- < / style>
195+
196+ @media (min- width: 768px ) and (max - width : 1024px ) {
197+ .drawer - main__search- results {
198+ grid- template- columns: repeat (2 , 1fr ); // 2 columns on tablets
199+ }
200+ }
201+ < / style>
0 commit comments