You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							67 lines
						
					
					
						
							1.7 KiB
						
					
					
				
			
		
		
	
	
							67 lines
						
					
					
						
							1.7 KiB
						
					
					
				| import { type Post } from 'contentlayer/generated';
 | |
| 
 | |
| /**
 | |
|  * Search for a query in a text.
 | |
|  * @returns A boolean indicating whether the query was found in the text.
 | |
|  */
 | |
| function searchHit(query: string, text: string) {
 | |
|   return text.toLowerCase().includes(query.toLowerCase());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Search for a query in a list of posts.
 | |
|  * @returns The posts that matched the query in descending order of relevance.
 | |
|  */
 | |
| export function searchPosts(query: string, posts: Array<Post>) {
 | |
|   const postsWithSearchHits = new Map<Post, number>();
 | |
| 
 | |
|   posts.forEach((post) => {
 | |
|     if (!query) return;
 | |
| 
 | |
|     const {
 | |
|       title,
 | |
|       excerpt,
 | |
|       tags,
 | |
|       body: { raw },
 | |
|     } = post;
 | |
| 
 | |
|     let searchHits = 0;
 | |
| 
 | |
|     if (tags.some((tag) => searchHit(query, tag))) {
 | |
|       searchHits += 10; // give tag hits heavy weight
 | |
|     }
 | |
|     if (searchHit(query, title)) {
 | |
|       searchHits += 10; // give title hits heavy weight
 | |
|     }
 | |
|     if (searchHit(query, excerpt)) {
 | |
|       searchHits += 5; // give excerpt hits lighter weight
 | |
|     }
 | |
|     if (searchHit(query, raw)) {
 | |
|       searchHits++; // give content hits lightest weight
 | |
|     }
 | |
| 
 | |
|     if (searchHits > 0) {
 | |
|       postsWithSearchHits.set(post, searchHits);
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   return Array.from(postsWithSearchHits.entries())
 | |
|     .sort(([, a], [, b]) => b - a)
 | |
|     .map(([post]) => post);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get all tags with their count
 | |
|  * @returns The tags with their count in descending order of count
 | |
|  */
 | |
| export function getTagsWithCount(posts: Array<Post>) {
 | |
|   const tagsWithCount = new Map<string, number>();
 | |
| 
 | |
|   posts.forEach((post) => {
 | |
|     post.tags.forEach((tag) => {
 | |
|       tagsWithCount.set(tag, (tagsWithCount.get(tag) ?? 0) + 1);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   return Array.from(tagsWithCount.entries()).sort(([, a], [, b]) => b - a);
 | |
| }
 | |
| 
 |