Add license; make corrections; cleanup

This commit is contained in:
2022-05-15 09:56:45 -04:00
parent 4e2a1adf9b
commit 7aadc47a3e
40 changed files with 355 additions and 493 deletions

View File

@@ -1,105 +0,0 @@
import { Dispatch, KeyboardEvent as ReactKeyboardEvent, MutableRefObject, SetStateAction } from 'react';
import Result from './fuzzy-result';
import style from '../styles/fuzzy.module.css';
export type FuzzyConstr = {
pages: Page[],
searchField: MutableRefObject<null>,
searchValue: string,
resultsValue: JSX.Element,
setResultsValue: Dispatch<SetStateAction<JSX.Element>>,
maxResults?: number
};
export type Page = {
title: string;
link: string;
};
export default class Fuzzy {
searchValue: string = '';
searchField: HTMLInputElement | null;
pages: Page[];
setResultsValue: Dispatch<SetStateAction<JSX.Element>>;
resultsValue: JSX.Element;
maxResults: number;
constructor(obj: FuzzyConstr) {
this.searchField = obj.searchField.current;
this.resultsValue = obj.resultsValue; // not yet implemented. have to look into lazy eval in js
this.setResultsValue = obj.setResultsValue;
this.searchValue = obj.searchValue || '';
this.pages = obj.pages
this.maxResults = obj.maxResults || this.pages.length;
}
searchKeyUpListener(e: ReactKeyboardEvent) {
this.showSearchResults();
}
showSearchResults(): void {
let searchValue: string = this.searchValue.toLowerCase();
searchValue = searchValue.trimStart().trimEnd();
if (this.maxResults !== undefined && searchValue === ''){
this.setResultsValue(
<>
<h2>Search PaulW.XYZ</h2>
<div>Enter a page or directory name in the search bar above.</div>
</>
)
return;
}
let results = [];
for (const [idx, page] of this.pages.entries()) {
const ret = this.fuzzySearch(page.title, searchValue);
if (ret === null)
continue;
results.push({ formatted: ret.formatted, link: page.link, score: ret.score });
}
if (results.length <= 0)
return this.setResultsValue(<>Unknown command or no matching pages found.</>);
results.sort((x, y) => { return x.score - y.score });
this.setResultsValue(
<>
{results.map((res: { formatted: JSX.Element[], link: string, score: number }, idx) => {
return (<Result
link={res.link}
formatted={res.formatted}
idx={idx}
key={`res-${idx}`} />);
})}
</>
);
}
fuzzySearch(findIn: string, find: string) {
let search = find.replace(/\s/g, '');
search = search.toLowerCase();
let tokens: string[] = findIn.split('');
let elements: JSX.Element[] = new Array(tokens.length);
let pc = 0;
let score = 0;
for (const [i, ch] of tokens.entries()) {
if (ch.toLowerCase() === search[pc]) {
score += i - pc;
elements[i] = (<span className={style.highlight}>{ch}</span>);
pc++;
if (search.length < pc)
return null;
continue;
}
elements[i] = (<>{ch}</>); // not very nice :(
}
if (search.length === pc)
return { formatted: elements, score: (score / search.length) };
return null;
}
}

View File

@@ -1,108 +0,0 @@
import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';
import Fuzzy from './_fuzzy';
import pages from '../public/pages.json';
import style from '../styles/fuzzy.module.css';
// @ts-ignore
import posts from '../posts/meta.json' // I do not like this
function FuzzyBar(): JSX.Element {
const searchField = useRef<any>(null);
const [searchValue, setSearchValue] = useState('');
const [resultsValue, setResultsValue] = useState(<></>);
let [metaKey, setMetaKey] = useState('Ctrl');
const [show, setShow] = useState(false);
let fuzz: Fuzzy | null = null;
let entries = [...pages];
for (const [k,v] of posts.entries()) {
const item = v as any;
if (item.title && item.slug)
entries.push({title: item.title, link: `posts/${item.slug}`});
}
try {
fuzz = new Fuzzy({
pages: entries,
searchField: searchField,
searchValue: searchValue,
resultsValue: resultsValue,
setResultsValue: setResultsValue,
maxResults: 5
});
} catch (e: any) {
console.error(e.message);
}
function searchInput(e: ChangeEvent<HTMLInputElement>) {
setSearchValue(e.target.value);
}
const toggleSearch = useCallback(() => {
setShow(!show);
fuzz?.showSearchResults();
searchField.current?.focus();
}, [fuzz, show]);
useEffect(() => {
if (window.navigator.userAgent.match(/mac[\s]?os/i))
setMetaKey('⌘ Cmd');
}, []);
useEffect(() => {
const event = (e: KeyboardEvent) => {
if (e.code === 'KeyK' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
toggleSearch();
}
if (e.code === 'KeyP' && (e.ctrlKey || e.metaKey) && e.shiftKey) {
e.preventDefault();
alert('not really sure what to do here lol');
}
if (show)
searchField.current?.focus();
return false;
}
window.addEventListener('keydown', event);
return () => { window.removeEventListener('keydown', event); }
}, [fuzz, show, toggleSearch]);
return (
<>
{
show ?
<div className={`fuzzynav ${style.container}`}>
<input type='text'
className={style.search}
value={searchValue}
placeholder='Go to ...'
ref={searchField}
onChange={searchInput}
onKeyUp={(e) => { fuzz?.searchKeyUpListener(e) }} />
<div
id='results'
className={style.results}>{resultsValue}</div>
</div>
: <></>
}
<a className={style.searchBar} onClick={toggleSearch}>
<span className={style.searchTerm}>Search</span>
<div className={style.keybind}>
<span className={style.key}>{metaKey}</span> <span className={style.key}>K</span>
</div>
</a>
</>
);
}
export default FuzzyBar;

View File

@@ -1,20 +0,0 @@
import style from '../styles/fuzzy.module.css';
import Link from 'next/link';
function Result(props: { formatted: JSX.Element[], key: string, link: string, idx: number }) {
return (
<Link href={props.link}>
<a className={style.hyperlink}>
<div className={style['hyperlink-name']}>
{props.formatted}
</div>
<div className={style['hyperlink-url']}>
{props.link}
</div>
</a>
</Link>
);
}
export default Result;

View File

@@ -1,6 +1,5 @@
import Meta from './meta';
import Title from './title';
// import FuzzyBar from './fuzzy-bar';
type ChildrenType = JSX.Element | Array<ChildrenType>;
@@ -16,7 +15,6 @@ function Layout({ name, title, children, ancestors }: LayoutProps) {
<>
<Meta name={name} ancestors={ancestors} />
<Title title={title} name={name} ancestors={ancestors} />
{/* <FuzzyBar /> */}
<div className='container'>
{children}
</div>

View File

@@ -7,7 +7,7 @@ function Meta({name, ancestors}
return name;
let path = '';
ancestors.map((obj) => {
ancestors.forEach((obj) => {
path = `${path}${obj.name} /`;
});

View File

@@ -2,19 +2,21 @@ import Link from 'next/link';
import Pages from '../public/pages.json';
function QuickLinks() {
return (<>
<div className='h2'>Quick Links</div>
{
Pages.map((obj, i) => {
const extern = obj.link.match(/^http/) && `blue extern` || '';
return (
<Link key={i} href={obj.link}>
<a className={`${extern} link button`}>{obj.title}</a>
</Link>
);
})
}
</>);
return (
<div className='block'>
<div className='h2'>Quick Links</div>
{
Object.entries(Pages).map(([title, link], i) => {
const extern = link.match(/^http/) && `blue extern` || '';
return (
<Link key={i} href={link}>
<a className={`${extern} link button`}>{title}</a>
</Link>
);
})
}
</div>
);
}
export default QuickLinks;

View File

@@ -2,24 +2,25 @@ import Link from "next/link";
import { NoteMeta } from "../util/slug";
function RecentNotes({ notesMeta }: { notesMeta: NoteMeta[] }) {
return (<>
<div className='h2'>Recent Notes</div>
{notesMeta?.slice(0, 10)
.map((note: any) => {
return <Link key={note.slug} href={`/notes/${note.slug}`}>
return (
<div className='block'>
<div className='h2'>Recent Notes</div>
{notesMeta?.slice(0, 10)
.map((note: any) => {
return <Link key={note.slug} href={`/notes/${note.slug}`}>
<a className={`button link`}>{note.title}</a>
</Link>
})
}
{
notesMeta.length > 10 &&
<div className={''}>
<Link href='/notes'>
<a className='h5'>More...</a>
</Link>
</div>
}
</>
})
}
{
notesMeta.length > 10 &&
<div className={''}>
<Link href='/notes'>
<a className='h5'>More...</a>
</Link>
</div>
}
</div>
);
}

View File

@@ -4,30 +4,31 @@ import { PostMeta } from "../util/slug";
import style from '../styles/recent-posts.module.css';
function RecentPosts({ postsMeta }: { postsMeta: PostMeta[] }) {
return (<>
<div className='h2'>Recent Posts</div>
<div className={style.container}>
{postsMeta?.slice(0, 10)
.map((post: any) => {
return <div className={style.block} key={post.slug}>
<Link href={`/posts/${post.slug}`}>
<a className={`${style.postTitle} h5`}>{post.title}</a>
</Link>
<span className={style.postDate}>
{date.prettyPrint(new Date(post.created_at))}
</span>
</div>
})}
</div>
{
postsMeta.length > 10 &&
<div className={style.more}>
<Link href='/posts'>
<a className='h5'>More...</a>
</Link>
return (
<div className='block'>
<div className='h2'>Recent Posts</div>
<div className={style.container}>
{postsMeta?.slice(0, 10)
.map((post: any) => {
return <div className={style.block} key={post.slug}>
<Link href={`/posts/${post.slug}`}>
<a className={`${style.postTitle} h5`}>{post.title}</a>
</Link>
<span className={style.postDate}>
{date.prettyPrint(new Date(post.created_at))}
</span>
</div>
})}
</div>
}
</>
{
postsMeta.length > 10 &&
<div className={style.more}>
<Link href='/posts'>
<a className='h5'>More...</a>
</Link>
</div>
}
</div>
);
}

View File

@@ -9,11 +9,11 @@ type propsObj = {
function createPathElements(ancestors: Array<{ name: string, path: string }>) {
let currentPath = '';
return ancestors.map((ancestor) => {
return ancestors.map((ancestor, id) => {
currentPath += `/${ancestor.path}`
return (
<>
<Link href={currentPath}>
<Link key={id + 1} href={currentPath}>
<a>{ancestor.name}</a>
</Link>
<> / </>