mirror of
https://github.com/wavetermdev/docusaurus-og.git
synced 2026-08-05 13:46:35 -07:00
feat: add support for searching across all docs instances
This commit is contained in:
@@ -13,30 +13,32 @@ const makeSearchPluginConfig = (
|
||||
plugins: PluginConfig[],
|
||||
options: PluginOptions,
|
||||
): PluginConfig[] => {
|
||||
const singleIndex = options.localSearch?.singleIndex ?? true
|
||||
|
||||
const docs = findDocInstances(plugins).map((plugin) =>
|
||||
validateDocPluginOptions(plugin![1]),
|
||||
)
|
||||
|
||||
return [
|
||||
[
|
||||
'@acid-info/logos-docusaurus-search-local',
|
||||
{
|
||||
hashed: true,
|
||||
indexDocs: true,
|
||||
indexBlog: false,
|
||||
indexPages: true,
|
||||
docsDir: docs.map((doc) => doc.path),
|
||||
searchContextByPaths: docs.map(({ routeBasePath, path }) =>
|
||||
routeBasePath === '/'
|
||||
? path
|
||||
: routeBasePath.startsWith('/')
|
||||
? routeBasePath.slice(1)
|
||||
: routeBasePath,
|
||||
),
|
||||
docsRouteBasePath: docs.map((doc) => doc.routeBasePath),
|
||||
} as Partial<SearchPluginOptions>,
|
||||
],
|
||||
]
|
||||
const config = {
|
||||
hashed: true,
|
||||
indexDocs: true,
|
||||
indexBlog: false,
|
||||
indexPages: true,
|
||||
docsDir: docs.map((doc) => doc.path),
|
||||
docsRouteBasePath: docs.map((doc) => doc.routeBasePath),
|
||||
} as Partial<SearchPluginOptions>
|
||||
|
||||
if (!singleIndex) {
|
||||
config.searchContextByPaths = docs.map(({ routeBasePath, path }) =>
|
||||
routeBasePath === '/'
|
||||
? path
|
||||
: routeBasePath.startsWith('/')
|
||||
? routeBasePath.slice(1)
|
||||
: routeBasePath,
|
||||
)
|
||||
}
|
||||
|
||||
return [['@acid-info/logos-docusaurus-search-local', config]]
|
||||
}
|
||||
|
||||
export default function logosPreset(
|
||||
|
||||
@@ -28,6 +28,10 @@ export type Contact = {
|
||||
|
||||
export type ContactInfo = Contact[]
|
||||
|
||||
export type LocalSearchConfig = {
|
||||
singleIndex?: boolean
|
||||
}
|
||||
|
||||
export type PresetConfig = {
|
||||
businessUnit: BusinessUnits
|
||||
contactInfo?: string
|
||||
@@ -42,4 +46,5 @@ export type PresetConfig = {
|
||||
}
|
||||
customSiteConfig?: boolean
|
||||
docs?: Partial<DocPluginOptions>
|
||||
localSearch?: LocalSearchConfig
|
||||
}
|
||||
|
||||
@@ -33,13 +33,10 @@ const findSearchContext = ({
|
||||
versionUrl: string
|
||||
searchContextByPaths: string | string[]
|
||||
}): string => {
|
||||
const { pathname } = window.location
|
||||
let pathname = window.location.pathname
|
||||
pathname = pathname.endsWith('/') ? pathname : pathname + '/'
|
||||
|
||||
if (
|
||||
searchContextByPaths === '' ||
|
||||
!Array.isArray(searchContextByPaths) ||
|
||||
!pathname.startsWith(versionUrl)
|
||||
)
|
||||
if (!Array.isArray(searchContextByPaths) || !pathname.startsWith(versionUrl))
|
||||
return ''
|
||||
|
||||
const uri = pathname.substring(versionUrl.length)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export const ensureTrailingString = (str: string, trail: string) =>
|
||||
str.endsWith(trail) ? str : str + trail
|
||||
|
||||
export const ensureTrailingSlash = (str: string) =>
|
||||
ensureTrailingString(str, '/')
|
||||
@@ -5,10 +5,12 @@ export const usePersistedHistory = <T = any>(
|
||||
options?: {
|
||||
equals?: (a: T, b: T) => boolean
|
||||
unique?: boolean
|
||||
maxItems?: number
|
||||
},
|
||||
) => {
|
||||
const unique = options?.unique ?? false
|
||||
const equals = options?.equals ?? ((a, b) => a === b)
|
||||
const maxItems = options?.maxItems ?? null
|
||||
|
||||
const [history, setHistory] = useLocalStorage<T[]>(
|
||||
'logos-docusaurus-theme-' + key,
|
||||
@@ -17,10 +19,11 @@ export const usePersistedHistory = <T = any>(
|
||||
|
||||
const add = (value: T) => {
|
||||
const arr = history ?? []
|
||||
setHistory([
|
||||
const newHistory = [
|
||||
value,
|
||||
...(unique ? arr.filter((item) => !equals(item, value)) : arr),
|
||||
])
|
||||
]
|
||||
setHistory(maxItems ? newHistory.slice(0, maxItems) : newHistory)
|
||||
}
|
||||
|
||||
const remove = (rm: (item: T, index: number) => boolean) => {
|
||||
|
||||
@@ -14,6 +14,7 @@ export const SearchBar: React.FC<{}> = ({}) => {
|
||||
const history = usePersistedHistory<SearchResultGroupItem>('search', {
|
||||
unique: true,
|
||||
equals: (a, b) => a.title === b.title && a.href === b.href,
|
||||
maxItems: 10,
|
||||
})
|
||||
const search = useSearch()
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
export const useProxiedGeneratedData = () => {
|
||||
const win = window as any
|
||||
|
||||
return win.getProxiedGeneratedData()
|
||||
}
|
||||
@@ -1,21 +1,19 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useProxiedGeneratedData } from './useProxiedGeneratedData'
|
||||
import { useVersionUrl } from './useVersionUrl'
|
||||
import { useSearchContextPath } from './useSearchContextPath'
|
||||
|
||||
export const useSearch = () => {
|
||||
const win = window as any
|
||||
const { createSearchInstance } = window as any
|
||||
|
||||
const data = useProxiedGeneratedData()
|
||||
const versionUrl = useVersionUrl()
|
||||
const searchContextPath = useSearchContextPath()
|
||||
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const search = useRef<any>(null)
|
||||
|
||||
const init = async () => {
|
||||
search.current = await win.createSearchInstance({
|
||||
search.current = await createSearchInstance({
|
||||
resultsLimit: 50,
|
||||
preferredVersionPath: versionUrl,
|
||||
searchContextByPaths: data.searchContextByPaths,
|
||||
preferredVersionPath: searchContextPath[0],
|
||||
searchContextByPaths: searchContextPath[1],
|
||||
})
|
||||
|
||||
await search.current.init()
|
||||
@@ -27,7 +25,7 @@ export const useSearch = () => {
|
||||
setLoaded(false)
|
||||
|
||||
init()
|
||||
}, [versionUrl])
|
||||
}, [searchContextPath[0], searchContextPath[1]])
|
||||
|
||||
return {
|
||||
loaded,
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { useActivePluginAndVersion } from '@docusaurus/plugin-content-docs/client'
|
||||
import { ensureTrailingSlash } from '../../../lib/string.utils'
|
||||
|
||||
const useProxiedData = () => {
|
||||
const win = window as any
|
||||
return win.getProxiedGeneratedData()
|
||||
}
|
||||
|
||||
const useSearchContextByPaths = () => {
|
||||
return useProxiedData().searchContextByPaths
|
||||
}
|
||||
|
||||
export const useSearchContextPath = () => {
|
||||
const separateContexts = useSearchContextByPaths()
|
||||
|
||||
const activePluginData = useActivePluginAndVersion()
|
||||
if (!activePluginData) return ['/', '']
|
||||
|
||||
const {
|
||||
activePlugin: {
|
||||
pluginData: { path: pluginPath },
|
||||
},
|
||||
activeVersion,
|
||||
} = activePluginData
|
||||
if (!activeVersion) return ['/', '']
|
||||
|
||||
return [
|
||||
pluginPath !== activeVersion.path
|
||||
? ensureTrailingSlash(activeVersion.path)
|
||||
: '/',
|
||||
separateContexts,
|
||||
]
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { useActivePlugin } from '@docusaurus/plugin-content-docs/client'
|
||||
import { useDocsPreferredVersion } from '@docusaurus/theme-common/internal'
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||
import { useProxiedGeneratedData } from './useProxiedGeneratedData'
|
||||
|
||||
export const useVersionUrl = () => {
|
||||
const {
|
||||
siteConfig: { baseUrl },
|
||||
} = useDocusaurusContext()
|
||||
|
||||
const { docsPluginIdForPreferredVersion } = useProxiedGeneratedData()
|
||||
|
||||
let result = baseUrl
|
||||
|
||||
const activePlugin = useActivePlugin()
|
||||
|
||||
const { preferredVersion } = useDocsPreferredVersion(
|
||||
activePlugin?.pluginId ?? docsPluginIdForPreferredVersion,
|
||||
)
|
||||
|
||||
result =
|
||||
preferredVersion && !preferredVersion.isLast
|
||||
? preferredVersion.path + '/'
|
||||
: result
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import ErrorBoundary from '@docusaurus/ErrorBoundary'
|
||||
import { useActivePlugin } from '@docusaurus/plugin-content-docs/lib/client/index.js'
|
||||
import React from 'react'
|
||||
import { SearchBar } from './SearchBar'
|
||||
@@ -6,7 +7,13 @@ const SearchBarWrapper: React.FC = () => {
|
||||
const activePlugin = useActivePlugin()
|
||||
if (!activePlugin) return <></>
|
||||
|
||||
return typeof window === 'undefined' ? <></> : <SearchBar />
|
||||
return typeof window === 'undefined' ? (
|
||||
<></>
|
||||
) : (
|
||||
<ErrorBoundary fallback={() => <></>}>
|
||||
<SearchBar />
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchBarWrapper
|
||||
|
||||
Reference in New Issue
Block a user