From 242e0d0375044e7d57420623fcf1d75bd126098f Mon Sep 17 00:00:00 2001 From: Dimitri POSTOLOV Date: Mon, 23 Dec 2024 15:49:16 +0800 Subject: [PATCH] [v4] search tweaks (#3852) * search tweaks * search tweaks * search tweaks * search tweaks * search tweaks * search tweaks * upd * upd --- .changeset/beige-owls-drum.md | 7 +++ docs/package.json | 2 +- examples/blog/package.json | 2 +- examples/docs/package.json | 2 +- examples/swr-site/package.json | 2 +- .../src/index.ts | 9 +++- .../src/mdx-components/index.tsx | 12 +++-- .../nextra/src/client/components/search.tsx | 37 ++++++++------ .../nextra/src/client/components/steps.tsx | 13 +++-- .../src/client/mdx-components/image.tsx | 10 +++- packages/nextra/src/env.d.ts | 8 ++- packages/nextra/src/types.ts | 13 +++++ pnpm-lock.yaml | 50 +++++++++---------- 13 files changed, 106 insertions(+), 61 deletions(-) create mode 100644 .changeset/beige-owls-drum.md diff --git a/.changeset/beige-owls-drum.md b/.changeset/beige-owls-drum.md new file mode 100644 index 0000000000..490699f51b --- /dev/null +++ b/.changeset/beige-owls-drum.md @@ -0,0 +1,7 @@ +--- +"nextra-theme-blog": patch +"nextra-theme-docs": patch +"nextra": patch +--- + +search tweaks diff --git a/docs/package.json b/docs/package.json index e6e8418dce..fd9eead4a8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -24,7 +24,7 @@ "@tailwindcss/postcss": "^4.0.0-beta.8", "@types/node": "^22.0.0", "@types/react": "^18.2.23", - "pagefind": "^1.1.1", + "pagefind": "^1.3.0", "tailwindcss": "^4.0.0-beta.8" }, "browserslist": [ diff --git a/examples/blog/package.json b/examples/blog/package.json index 99e7260630..d2e892d14f 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -17,6 +17,6 @@ "react-dom": "18.3.1" }, "devDependencies": { - "pagefind": "^1.1.1" + "pagefind": "^1.3.0" } } diff --git a/examples/docs/package.json b/examples/docs/package.json index 45880d3852..16293a5aa6 100644 --- a/examples/docs/package.json +++ b/examples/docs/package.json @@ -16,6 +16,6 @@ "react-dom": "18.3.1" }, "devDependencies": { - "pagefind": "^1.1.1" + "pagefind": "^1.3.0" } } diff --git a/examples/swr-site/package.json b/examples/swr-site/package.json index 882fba9092..326ec14665 100644 --- a/examples/swr-site/package.json +++ b/examples/swr-site/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@next/bundle-analyzer": "^14.2.13", "@tailwindcss/postcss": "^4.0.0-beta.8", - "pagefind": "^1.1.1", + "pagefind": "^1.3.0", "tailwindcss": "^4.0.0-beta.8" }, "browserslist": [ diff --git a/packages/esbuild-react-compiler-plugin/src/index.ts b/packages/esbuild-react-compiler-plugin/src/index.ts index 8ccbce27de..b5933a1948 100644 --- a/packages/esbuild-react-compiler-plugin/src/index.ts +++ b/packages/esbuild-react-compiler-plugin/src/index.ts @@ -14,13 +14,18 @@ const DEFAULT_REACT_COMPILER_CONFIG = { filename: string, result: { kind: 'CompileError' | 'CompileSuccess' } ) { + const relativeFilePath = path.relative(process.cwd(), filename) if (result.kind === 'CompileSuccess') { - console.info('šŸš€ File', filename, 'was optimized with react-compiler') + console.info( + 'šŸš€ File', + relativeFilePath, + 'was optimized with react-compiler' + ) return } console.error( 'āŒ File', - filename, + relativeFilePath, 'was not optimized with react-compiler' ) console.error(result) diff --git a/packages/nextra-theme-docs/src/mdx-components/index.tsx b/packages/nextra-theme-docs/src/mdx-components/index.tsx index 47054ae081..dfd7adda74 100644 --- a/packages/nextra-theme-docs/src/mdx-components/index.tsx +++ b/packages/nextra-theme-docs/src/mdx-components/index.tsx @@ -82,21 +82,25 @@ const DEFAULT_COMPONENTS = getNextraMDXComponents({ {...props} /> ), - wrapper({ toc, children, ...props }) { + wrapper({ toc, children, metadata, ...props }) { // @ts-expect-error fixme toc = toc.map(item => ({ ...item, value: removeLinks(item.value) })) return ( -
+
- +
{children} diff --git a/packages/nextra/src/client/components/search.tsx b/packages/nextra/src/client/components/search.tsx index 64c6318ea8..577ab58b7d 100644 --- a/packages/nextra/src/client/components/search.tsx +++ b/packages/nextra/src/client/components/search.tsx @@ -12,6 +12,7 @@ import NextLink from 'next/link' import { useRouter } from 'next/navigation' import type { FC, FocusEventHandler, ReactElement, SyntheticEvent } from 'react' import { useDeferredValue, useEffect, useRef, useState } from 'react' +import type { PagefindSearchOptions } from '../../types.js' import { useMounted } from '../hooks/use-mounted.js' import { InformationCircleIcon, SpinnerIcon } from '../icons/index.js' @@ -46,9 +47,10 @@ type SearchProps = { loading?: ReactElement | string placeholder?: string className?: string + searchOptions?: PagefindSearchOptions } -const INPUTS = new Set(['input', 'select', 'button', 'textarea']) +const INPUTS = new Set(['INPUT', 'SELECT', 'BUTTON', 'TEXTAREA']) const DEV_SEARCH_NOTICE = ( <> @@ -69,7 +71,8 @@ export const Search: FC = ({ emptyResult = 'No results found.', errorText = 'Failed to load search index.', loading = 'Loadingā€¦', - placeholder = 'Search documentationā€¦' + placeholder = 'Search documentationā€¦', + searchOptions }) => { const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState('') @@ -105,7 +108,11 @@ export const Search: FC = ({ return } } - const { results } = await window.pagefind!.search(value) + const { results } = + await window.pagefind!.debouncedSearch( + value, + searchOptions + ) const data = await Promise.all(results.map(o => o.data())) setResults( @@ -121,26 +128,23 @@ export const Search: FC = ({ setIsLoading(false) } handleSearch(deferredSearch) - }, [deferredSearch]) + }, [deferredSearch]) // eslint-disable-line react-hooks/exhaustive-deps -- ignore searchOptions const router = useRouter() const [focused, setFocused] = useState(false) const mounted = useMounted() - const inputRef = useRef(null) + const inputRef = useRef(null!) useEffect(() => { function handleKeyDown(event: globalThis.KeyboardEvent) { - const input = inputRef.current - const { activeElement } = document - const tagName = activeElement?.tagName.toLowerCase() + const el = document.activeElement if ( - !input || - !tagName || - INPUTS.has(tagName) || - // @ts-expect-error -- fixme - activeElement?.isContentEditable - ) + !el || + INPUTS.has(el.tagName) || + (el as HTMLElement).isContentEditable + ) { return + } if ( event.key === '/' || (event.key === 'k' && @@ -148,7 +152,7 @@ export const Search: FC = ({ ) { event.preventDefault() // prevent to scroll to top - input.focus({ preventScroll: true }) + inputRef.current.focus({ preventScroll: true }) } } @@ -193,7 +197,7 @@ export const Search: FC = ({ if (!searchResult) return // Calling before navigation so selector `html:not(:has(*:focus))` in styles.css will work, // and we'll have padding top since input is not focused - inputRef.current?.blur() + inputRef.current.blur() router.push(searchResult.url) setSearch('') } @@ -202,6 +206,7 @@ export const Search: FC = ({
> = ({ @@ -16,12 +16,11 @@ export const Steps: FC> = ({ 'x:dark:border-neutral-800', className )} - style={ - { - ...style, - '--counter-id': id - } as CSSProperties - } + style={{ + ...style, + // @ts-expect-error -- fixme + '--counter-id': id + }} {...props} > {children} diff --git a/packages/nextra/src/client/mdx-components/image.tsx b/packages/nextra/src/client/mdx-components/image.tsx index 520ed8ed35..f134f5cb3b 100644 --- a/packages/nextra/src/client/mdx-components/image.tsx +++ b/packages/nextra/src/client/mdx-components/image.tsx @@ -18,8 +18,14 @@ This is Turbopack bug, which will not occurs on production (since Webpack is use } } const ComponentToUse = typeof props.src === 'object' ? NextImage : 'img' - // @ts-expect-error -- fixme - return + return ( + // @ts-expect-error -- fixme + + ) }) Image.displayName = 'Image' diff --git a/packages/nextra/src/env.d.ts b/packages/nextra/src/env.d.ts index 17710ae4be..f4af3abffe 100644 --- a/packages/nextra/src/env.d.ts +++ b/packages/nextra/src/env.d.ts @@ -1,7 +1,13 @@ declare namespace globalThis { + import type { PagefindSearchOptions } from './types.js' var pagefind: | { - search: (query: string) => Promise<{ + // https://github.com/CloudCannon/pagefind/blob/2a0aa90cfb78bb8551645ac9127a1cd49cf54add/pagefind_web_js/lib/coupled_search.ts#L600 + debouncedSearch: ( + term: string, + options?: PagefindSearchOptions, + debounceTimeoutMs?: number + ) => Promise<{ results: { data: () => Promise id: string diff --git a/packages/nextra/src/types.ts b/packages/nextra/src/types.ts index fa7e0aceb4..2a69b16b2c 100644 --- a/packages/nextra/src/types.ts +++ b/packages/nextra/src/types.ts @@ -102,3 +102,16 @@ export type MDXWrapper = FC<{ }> export type MetaRecord = Record> + +// Copied from https://github.com/CloudCannon/pagefind/blob/2a0aa90cfb78bb8551645ac9127a1cd49cf54add/pagefind_web_js/types/index.d.ts#L72-L82 +/** Options that can be passed to pagefind.search() */ +export type PagefindSearchOptions = { + /** If set, this call will load all assets but return before searching. Prefer using pagefind.preload() instead */ + preload?: boolean + /** Add more verbose console logging for this search query */ + verbose?: boolean + /** The set of filters to execute with this search. Input type is extremely flexible, see the filtering docs for details */ + filters?: object + /** The set of sorts to use for this search, instead of relevancy */ + sort?: object +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb40225702..14e8295fb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -102,8 +102,8 @@ importers: specifier: ^18.2.23 version: 18.3.12 pagefind: - specifier: ^1.1.1 - version: 1.2.0 + specifier: ^1.3.0 + version: 1.3.0 tailwindcss: specifier: ^4.0.0-beta.8 version: 4.0.0-beta.8 @@ -127,8 +127,8 @@ importers: version: 18.3.1(react@18.3.1) devDependencies: pagefind: - specifier: ^1.1.1 - version: 1.2.0 + specifier: ^1.3.0 + version: 1.3.0 examples/docs: dependencies: @@ -149,8 +149,8 @@ importers: version: 18.3.1(react@18.3.1) devDependencies: pagefind: - specifier: ^1.1.1 - version: 1.2.0 + specifier: ^1.3.0 + version: 1.3.0 examples/swr-site: dependencies: @@ -183,8 +183,8 @@ importers: specifier: ^4.0.0-beta.8 version: 4.0.0-beta.8 pagefind: - specifier: ^1.1.1 - version: 1.2.0 + specifier: ^1.3.0 + version: 1.3.0 tailwindcss: specifier: ^4.0.0-beta.8 version: 4.0.0-beta.8 @@ -4091,40 +4091,40 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - /@pagefind/darwin-arm64@1.2.0: - resolution: {integrity: sha512-pHnPL2rm4xbe0LqV376g84hUIsVdy4PK6o2ACveo0DSGoC40eOIwPUPftnUPUinSdDWkkySaL5FT5r9hsXk0ZQ==} + /@pagefind/darwin-arm64@1.3.0: + resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@pagefind/darwin-x64@1.2.0: - resolution: {integrity: sha512-q2tcnfvcRyx0GnrJoUQJ5bRpiFNtI8DZWM6a4/k8sNJxm2dbM1BnY5hUeo4MbDfpb64Qc1wRMcvBUSOaMKBjfg==} + /@pagefind/darwin-x64@1.3.0: + resolution: {integrity: sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@pagefind/linux-arm64@1.2.0: - resolution: {integrity: sha512-wVtLOlF9AUrwLovP9ZSEKOYnwIVrrxId4I2Mz02Zxm3wbUIJyx8wHf6LyEf7W7mJ6rEjW5jtavKAbngKCAaicg==} + /@pagefind/linux-arm64@1.3.0: + resolution: {integrity: sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@pagefind/linux-x64@1.2.0: - resolution: {integrity: sha512-Lo5aO2bA++sQTeEWzK5WKr3KU0yzVH5OnTY88apZfkgL4AVfXckH2mrOU8ouYKCLNPseIYTLFEdj0V5xjHQSwQ==} + /@pagefind/linux-x64@1.3.0: + resolution: {integrity: sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@pagefind/windows-x64@1.2.0: - resolution: {integrity: sha512-tGQcwQAb5Ndv7woc7lhH9iAdxOnTNsgCz8sEBbsASPB2A0uI8BWBmVdf2GFLQkYHqnnqYuun63sa+UOzB7Ah3g==} + /@pagefind/windows-x64@1.3.0: + resolution: {integrity: sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==} cpu: [x64] os: [win32] requiresBuild: true @@ -9948,15 +9948,15 @@ packages: /package-manager-detector@0.2.2: resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} - /pagefind@1.2.0: - resolution: {integrity: sha512-sFVv5/x73qCp9KlLHv8/uWDv7rG1tsWcG9MuXc5YTrXIrb8c1Gshm9oc5rMLXNZILXUWai8WczqaK4jjroEzng==} + /pagefind@1.3.0: + resolution: {integrity: sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==} hasBin: true optionalDependencies: - '@pagefind/darwin-arm64': 1.2.0 - '@pagefind/darwin-x64': 1.2.0 - '@pagefind/linux-arm64': 1.2.0 - '@pagefind/linux-x64': 1.2.0 - '@pagefind/windows-x64': 1.2.0 + '@pagefind/darwin-arm64': 1.3.0 + '@pagefind/darwin-x64': 1.3.0 + '@pagefind/linux-arm64': 1.3.0 + '@pagefind/linux-x64': 1.3.0 + '@pagefind/windows-x64': 1.3.0 dev: true /parent-module@1.0.1: