From d2d813c04ce37cdb4a283dcd60b7986882970be5 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 1 Apr 2021 14:18:51 +0200 Subject: simple fuzzy search working --- components/tag.tsx | 2 +- package.json | 1 + pages/search.tsx | 52 +++++++++++++++++++++++++++++++++++++++------------- yarn.lock | 5 +++++ 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/components/tag.tsx b/components/tag.tsx index 48c75ce..477b8e2 100644 --- a/components/tag.tsx +++ b/components/tag.tsx @@ -5,7 +5,7 @@ export default function Tags(props: { }) { return
Tags: - {props.tags.map(tag => )} + {props.tags.map(tag => )}
} diff --git a/package.json b/package.json index 2671cdc..636b466 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", + "fuse.js": "^6.4.6", "next": "10.0.9", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/pages/search.tsx b/pages/search.tsx index 8053d4a..af9bfeb 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -1,21 +1,20 @@ import { useState, useEffect } from 'react'; +import Fuse from 'fuse.js'; import Navbar from '../components/navbar'; -import { FormEvent } from 'react'; -import { ArticleMeta } from './post/[id]'; import Tags from '../components/tag' import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined'; -function SearchBar(props: { - searchFunction: (event?: FormEvent) => void; -}) { +function SearchBar(props: { searchFunction: () => void }) { return
-
- - - -
+ props.searchFunction()} + autoComplete="off"/> +
} @@ -54,12 +53,39 @@ function Posts(props: { posts: Array }) { 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", + "urlname", + "tags" + ], + isCaseSensitive: false + }) useEffect(() => {(async () => { + var query = new URLSearchParams(window.location.search).get("q") || ""; + if(query) + (document.getElementById("searchInput") as HTMLInputElement).value = query; + setQuery(query); + var posts = await fetch("/posts.json"); setPosts(await posts.json()); })()}, []); + useEffect(() => { + if(query.length == 0) { + setVisiblePosts(posts.posts) + } else { + setVisiblePosts(fuse.search(query).map(res => res.item)) + } + }, [query]); + return
@@ -71,10 +97,10 @@ export default function SearchPage() {
- ) => { - event?.preventDefault(); + { + setTimeout(() => setQuery((document.getElementById("searchInput") as HTMLInputElement).value)); }}/> - +
diff --git a/yarn.lock b/yarn.lock index ce40569..6579763 100644 --- a/yarn.lock +++ b/yarn.lock @@ -834,6 +834,11 @@ fsevents@~2.3.1: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fuse.js@^6.4.6: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.4.6.tgz#62f216c110e5aa22486aff20be7896d19a059b79" + integrity sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw== + get-orientation@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947" -- cgit v1.2.3