1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-11-17 10:35:10 +00:00

Refactor web search index

This commit is contained in:
Brenden Matthews 2024-02-26 13:18:49 -05:00
parent 5dd632c991
commit f4a8124592
15 changed files with 564 additions and 400 deletions

3
web/.gitignore vendored
View File

@ -42,3 +42,6 @@ yarn-error.log*
# Cypress videos
cypress/videos
# Fuse.js index (we generate this on the fly)
public/static/fuse-index.json

View File

@ -3,17 +3,14 @@ import { useRouter } from 'next/router'
import GitHub from './GitHub'
import ThemeSwitcher from './ThemeSwitcher'
import * as React from 'react'
import Search from './Search'
type HeaderProps = {
name: string
setDarkMode: (state: boolean) => void
searchIndex: SearchIndex
}
import * as React from 'react'
import Search from './Search'
import { SearchIndex, SearchItem } from '../utils/search'
import Fuse, { IFuseOptions } from 'fuse.js'
interface NavLinkProps {
href: string
name: string
@ -34,20 +31,8 @@ const NavLink: React.FunctionComponent<NavLinkProps> = (props) => {
)
}
export default function Header({
name,
setDarkMode,
searchIndex,
}: HeaderProps) {
export default function Header({ name, setDarkMode }: HeaderProps) {
const router = useRouter()
const fuse = React.useMemo(() => {
const options: IFuseOptions<SearchItem> = {}
return new Fuse(
searchIndex.list,
options,
Fuse.parseIndex(searchIndex.index)
)
}, [searchIndex])
return (
<div className="border-b-1 backdrop-blur-lg bg-white dark:bg-black bg-opacity-20 dark:bg-opacity-20 transition">
@ -65,7 +50,7 @@ export default function Header({
</div>
)}
<div className="flex-grow" />
<Search fuse={fuse} />
<Search />
<div className="flex">
<div className="border-r mx-1 px-1 border-slate-700">
<a href="https://github.com/brndnmtthws/conky">

View File

@ -1,5 +1,4 @@
import { useEffect, useState } from 'react'
import { SearchIndex } from '../utils/search'
import Footer from './Footer'
import Header from './Header'
@ -17,10 +16,9 @@ function darkModeDefault() {
interface LayoutProps {
children: React.ReactNode
searchIndex: SearchIndex
}
export default function Layout({ children, searchIndex }: LayoutProps) {
export default function Layout({ children }: LayoutProps) {
const [darkMode, setDarkMode] = useState(darkModeDefault())
useEffect(() => {
@ -48,11 +46,7 @@ export default function Layout({ children, searchIndex }: LayoutProps) {
return (
<div>
<div className="sticky top-0 z-10 h-16">
<Header
searchIndex={searchIndex}
name="Conky"
setDarkMode={setDarkMode}
/>
<Header name="Conky" setDarkMode={setDarkMode} />
</div>
<div className="relative pb-4">
<div className="flex flex-col items-center max-w-3xl w-full mx-auto">

View File

@ -1,13 +1,11 @@
import Fuse, { FuseResult } from 'fuse.js'
import React, { Fragment, useCallback, useEffect, useState } from 'react'
import { Search as SearchIcon } from 'react-feather'
import { SearchItem } from '../utils/search'
import { SearchIndex, SearchItem } from '../utils/search'
import { Dialog, Transition, Combobox } from '@headlessui/react'
import { useRouter } from 'next/router'
export interface SearchProps {
fuse: Fuse<SearchItem>
}
export interface SearchProps {}
interface SearchResultProps {
result: FuseResult<SearchItem>
@ -57,12 +55,25 @@ const SearchResult: React.FunctionComponent<SearchResultProps> = (props) => {
)
}
const Search: React.FunctionComponent<SearchProps> = ({ fuse }) => {
const Search: React.FunctionComponent<SearchProps> = () => {
const router = useRouter()
const [searchText, setSearchText] = useState('')
const [searchResults, setSearchResults] = useState<FuseResult<SearchItem>[]>(
[]
)
const [fuse, setFuse] = React.useState<Fuse<SearchItem> | undefined>(
undefined
)
const fusePromise = async () => {
const data = await fetch('/static/fuse-index.json')
console.log(data)
const searchIndex: SearchIndex = await data.json()
console.log(searchIndex)
return new Fuse(searchIndex.list, {}, Fuse.parseIndex(searchIndex.index))
}
React.useEffect(() => {
fusePromise().then((fuse) => setFuse(fuse))
}, [])
const [isOpen, setIsOpen] = useState(false)
const handleKeyPress = useCallback(
@ -89,6 +100,14 @@ const Search: React.FunctionComponent<SearchProps> = ({ fuse }) => {
}
}, [handleKeyPress])
if (!fuse) {
return (
<div className="flex items-center ml-2">
<SearchIcon size={32} />
</div>
)
}
const setSearch = (value: string) => {
setSearchText(value)
const searchResult = fuse.search(value)

811
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,14 +11,15 @@
"url": "https://github.com/brndnmtthws/conky/issues"
},
"scripts": {
"dev": "next dev",
"dev:watch": "next-remote-watch ./documents",
"build": "next build",
"start": "next start",
"export": "next build && next export",
"dev": "npm run write-search-index && next dev",
"dev:watch": "npm run write-search-index && next-remote-watch ./documents",
"build": "npm run write-search-index && next build",
"start": "npm run write-search-index && next start",
"export": "npm run write-search-index && next build && next export",
"lint": "next lint",
"e2e": "start-server-and-test dev http://localhost:3000 \"cypress open --e2e\"",
"e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\""
"e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\"",
"write-search-index": "tsx ./scripts/write-search-index.ts"
},
"dependencies": {
"@fontsource-variable/fira-code": "^5.0.16",
@ -64,6 +65,7 @@
"remark-rehype": "^11.1.0",
"start-server-and-test": "^2.0.3",
"tailwindcss": "^3.4.1",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
}
}

View File

@ -1,17 +1,10 @@
import { Document } from '../utils/mdx-utils'
import Layout from '../components/Layout'
import SEO from '../components/SEO'
import { getSearchIndex, SearchIndex } from '../utils/search'
import Doggy from '../components/Doggy'
interface IndexProps {
documents: Document[]
searchIndex: SearchIndex
}
export default function FourOhFour({ searchIndex }: IndexProps) {
export default function FourOhFour() {
return (
<Layout searchIndex={searchIndex}>
<Layout>
<SEO title="Conky" description="Conky documentation" />
<main className="w-full">
<div className="flex flex-col items-center">
@ -25,7 +18,5 @@ export default function FourOhFour({ searchIndex }: IndexProps) {
}
export function getStaticProps() {
const searchIndex = getSearchIndex()
return { props: { searchIndex } }
return { props: {} }
}

View File

@ -6,16 +6,14 @@ import {
filterDesc,
} from '../utils/doc-utils'
import Docs from '../components/Docs'
import { getSearchIndex, SearchIndex } from '../utils/search'
export interface ConfigSettingsProps {
config_settings: Documentation
searchIndex: SearchIndex
}
export default function ConfigSettings(props: ConfigSettingsProps) {
return (
<Layout searchIndex={props.searchIndex}>
<Layout>
<SEO
title="Conky Config settings"
description="Conky configuration settings"
@ -34,7 +32,6 @@ export default function ConfigSettings(props: ConfigSettingsProps) {
export async function getStaticProps() {
const config_settings = filterDesc(getConfigSettings())
const searchIndex = getSearchIndex()
return { props: { config_settings, searchIndex } }
return { props: { config_settings } }
}

View File

@ -8,7 +8,6 @@ import {
import Layout from '../../components/Layout'
import SEO from '../../components/SEO'
import { GetStaticProps } from 'next'
import { getSearchIndex, SearchIndex } from '../../utils/search'
import Link from 'next/link'
import { unified } from 'unified'
import rehypeReact from 'rehype-react'
@ -27,13 +26,11 @@ interface FrontMatter {
interface DocumentPageProps {
source: string
frontMatter: FrontMatter
searchIndex: SearchIndex
}
export default function DocumentPage({
source,
frontMatter,
searchIndex,
}: DocumentPageProps) {
const [children, setChildren] = useState(createElement(Fragment))
@ -53,7 +50,7 @@ export default function DocumentPage({
)
return (
<Layout searchIndex={searchIndex}>
<Layout>
<SEO
title={`${frontMatter.title}`}
description={frontMatter.description}
@ -80,11 +77,9 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
const { source, data } = await getDocumentBySlug(params.slug as string)
const prevDocument = getPreviousDocumentBySlug(params.slug as string)
const nextDocument = getNextDocumentBySlug(params.slug as string)
const searchIndex = getSearchIndex()
return {
props: {
searchIndex,
source,
frontMatter: data,
prevDocument,

View File

@ -3,7 +3,6 @@ import { getDocuments, Document } from '../utils/mdx-utils'
import Layout from '../components/Layout'
import ArrowIcon from '../components/ArrowIcon'
import SEO from '../components/SEO'
import { getSearchIndex, SearchIndex } from '../utils/search'
const pages = [
{
@ -48,12 +47,11 @@ const IndexItem: React.FunctionComponent<IndexItemProps> = (props) => {
interface IndexProps {
documents: Document[]
searchIndex: SearchIndex
}
export default function Index({ documents, searchIndex }: IndexProps) {
export default function Index({ documents }: IndexProps) {
return (
<Layout searchIndex={searchIndex}>
<Layout>
<SEO title="Conky" description="Conky documentation" />
<main className="w-full">
<div className="w-full">
@ -87,7 +85,6 @@ export default function Index({ documents, searchIndex }: IndexProps) {
export function getStaticProps() {
const documents = getDocuments()
const searchIndex = getSearchIndex()
return { props: { documents, searchIndex } }
return { props: { documents } }
}

View File

@ -2,16 +2,14 @@ import Layout from '../components/Layout'
import SEO from '../components/SEO'
import { getLua, Documentation, filterDesc } from '../utils/doc-utils'
import Docs from '../components/Docs'
import { getSearchIndex, SearchIndex } from '../utils/search'
export interface LuaProps {
lua: Documentation
searchIndex: SearchIndex
}
export default function Lua(props: LuaProps) {
return (
<Layout searchIndex={props.searchIndex}>
<Layout>
<SEO title="Conky Lua API" description="Conky Lua API documentation" />
<main className="w-full">
<div>
@ -27,7 +25,6 @@ export default function Lua(props: LuaProps) {
export async function getStaticProps() {
const lua = filterDesc(getLua())
const searchIndex = getSearchIndex()
return { props: { lua, searchIndex } }
return { props: { lua } }
}

View File

@ -2,16 +2,14 @@ import Layout from '../components/Layout'
import SEO from '../components/SEO'
import { getVariables, Documentation, filterDesc } from '../utils/doc-utils'
import Docs from '../components/Docs'
import { getSearchIndex, SearchIndex } from '../utils/search'
export interface VariablesProps {
variables: Documentation
searchIndex: SearchIndex
}
export default function Variables(props: VariablesProps) {
return (
<Layout searchIndex={props.searchIndex}>
<Layout>
<SEO
title="Conky Variables"
description="Conky object variables documentation"
@ -28,7 +26,6 @@ export default function Variables(props: VariablesProps) {
export async function getStaticProps() {
const variables = filterDesc(getVariables())
const searchIndex = getSearchIndex()
return { props: { variables, searchIndex } }
return { props: { variables } }
}

View File

@ -0,0 +1,7 @@
import { writeSearchIndex } from '../utils/search-serde'
async function main() {
await writeSearchIndex()
}
main()

View File

@ -0,0 +1,9 @@
import * as fs from 'fs/promises'
import { createSearchIndex } from './search'
export async function writeSearchIndex() {
await fs.mkdir('public').catch(() => {})
await fs.mkdir('public/static').catch(() => {})
const index = createSearchIndex()
await fs.writeFile('public/static/fuse-index.json', JSON.stringify(index))
}

View File

@ -1,10 +1,12 @@
import Fuse, { FuseIndexRecords } from 'fuse.js'
import { getConfigSettings, getLua, getVariables } from './doc-utils'
export interface SearchItem {
kind: string
name: string
desc: string
}
export interface SearchIndex {
index: {
keys: readonly string[]
@ -13,7 +15,7 @@ export interface SearchIndex {
list: SearchItem[]
}
export function getSearchIndex() {
export function createSearchIndex(): SearchIndex {
const cs: SearchItem[] = getConfigSettings().values.map((v) => ({
kind: 'config',
name: v.name,