import Fuse from 'fuse.js'; import { useEffect, useState } from 'react'; import Navbar from '../components/navbar'; import Tags from '../components/tag'; import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined'; function SearchBar(props: { searchFunction: () => void; }) { return
props.searchFunction()} spellCheck='false' autoComplete='off' />
; } export interface Post { title: string; subtitle: string; author: string; date: string; id: string; cover: string; tags: Array; } export interface PostsInfo { valid_tags: Array; posts: Array; } function Post(props: { post: Post; }) { return {props.post.title} {props.post.subtitle &&

{props.post.subtitle}

}

Written by {props.post.author} on {new Date(props.post.date).toLocaleString('en-us', { month: 'long', day: 'numeric', })}

; } function Posts(props: { posts: Array; }) { return
{props.posts.map(post => )}
; } function searchFilter(query: string, tags: Array) { var output = { query: '', tags: [], }; // remove string literals from tag matching var queryWithoutLiterals = query.replace(/\".+?\"/g, ''); // find tags and remove them from the query tags.forEach(tag => { var index = queryWithoutLiterals.indexOf(tag); if (index == -1) return; // remove tag from query queryWithoutLiterals = queryWithoutLiterals.substr(0, index) + queryWithoutLiterals.substr(index + tag.length); output.tags.push(tag); }); // add back in the string literals (janky just gets pasted on end) output.query = queryWithoutLiterals + ' ' + (query.match(/\".+?\"/g) ?.map(r => r.substr(1, r.length - 2)) .join(' ') || ''); return output; } export default function SearchPage() { var [posts, setPosts] = useState({ posts: [], valid_tags: [] }); var [query, setQuery] = useState('-'); var [visiblePosts, setVisiblePosts] = useState>([]); var fuse = new Fuse(posts.posts, { keys: [ 'title', 'subtitle', 'author', 'date', 'id', 'tags', ], isCaseSensitive: false, }); useEffect(() => { (async () => { var query = new URLSearchParams(window.location.search).get('q') || ''; if (query) { (document.getElementById('searchInput') as HTMLInputElement).value = query; } var posts = await fetch('/posts.json'); var postsJson: PostsInfo = await posts.json(); setPosts(postsJson); setQuery(query); })(); }, []); useEffect(() => { var search = searchFilter(query, posts.valid_tags); if (search.query.length == 0) { var results = posts.posts; } else { var fuseSearch = fuse.search(search.query); var results = fuseSearch.map(res => res.item); } results = results.filter(result => { for (var i in search.tags) { if (!result.tags.includes(search.tags[i])) { return false; } } return true; }); results = results.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); setVisiblePosts(results); }, [query]); return

Search for posts

{ setTimeout(() => setQuery((document.getElementById('searchInput') as HTMLInputElement).value)); }} />
; }