diff --git a/.changeset/witty-pans-crash.md b/.changeset/witty-pans-crash.md new file mode 100644 index 0000000000..9b9b9ae86c --- /dev/null +++ b/.changeset/witty-pans-crash.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight-docsearch': minor +--- + +Adds a Starlight plugin to support using Algolia DocSearch as the Starlight search provider. diff --git a/docs/src/content/docs/guides/overriding-components.md b/docs/src/content/docs/guides/overriding-components.md index 8b13f90e98..5458cdb936 100644 --- a/docs/src/content/docs/guides/overriding-components.md +++ b/docs/src/content/docs/guides/overriding-components.md @@ -1,8 +1,6 @@ --- title: Overriding Components description: Learn how to override Starlight’s built-in components to add custom elements to your documentation site’s UI. -sidebar: - badge: New --- Starlight’s default UI and configuration options are designed to be flexible and work for a range of content. Much of Starlight's default appearance can be customized with [CSS](/guides/css-and-tailwind/) and [configuration options](/guides/customization/). diff --git a/docs/src/content/docs/guides/site-search.mdx b/docs/src/content/docs/guides/site-search.mdx new file mode 100644 index 0000000000..afc7edc7f3 --- /dev/null +++ b/docs/src/content/docs/guides/site-search.mdx @@ -0,0 +1,166 @@ +--- +title: Site Search +description: Learn about Starlight’s built-in site search features and how to customize them. +sidebar: + badge: New +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +By default, Starlight sites include full-text search powered by [Pagefind](https://pagefind.app/), which is a fast and low-bandwidth search tool for static sites. + +No configuration is required to enable search. Build and deploy your site, then use the search bar in the site header to find content. + +## Hide content in search results + +### Exclude a page + +To exclude a page from your search index, add [`pagefind: false`](/reference/frontmatter/#pagefind) to the page’s frontmatter: + +```md title="src/content/docs/not-indexed.md" ins={3} +--- +title: Content to hide from search +pagefind: false +--- +``` + +### Exclude part of a page + +Pagefind will ignore content inside an element with the [`data-pagefind-ignore`](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index) attribute. + +In the following example, the first paragraph will display in search results, but the contents of the `
` will not: + +```md title="src/content/docs/partially-indexed.md" ins="data-pagefind-ignore" +--- +title: Partially indexed page +--- + +This text will be discoverable via search. + +
+ +This text will be hidden from search. + +
+``` + +## Alternative search providers + +### Algolia DocSearch + +If you have access to [Algolia’s DocSearch program](https://docsearch.algolia.com/) and want to use it instead of Pagefind, you can use the official Starlight DocSearch plugin. + +1. Install `@astrojs/starlight-docsearch`: + + + + + + ```sh + npm install @astrojs/starlight-docsearch + ``` + + + + + + ```sh + pnpm install @astrojs/starlight-docsearch + ``` + + + + + + ```sh + yarn add @astrojs/starlight-docsearch + ``` + + + + + +2. Add DocSearch to your Starlight [`plugins`](/reference/configuration/#plugins) config in `astro.config.mjs` and pass it your Algolia `appId`, `apiKey`, and `indexName`: + + ```js ins={4,10-16} + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import starlight from '@astrojs/starlight'; + import starlightDocSearch from '@astrojs/starlight-docsearch'; + + export default defineConfig({ + integrations: [ + starlight({ + title: 'Site with DocSearch', + plugins: [ + starlightDocSearch({ + appId: 'YOUR_APP_ID', + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', + }), + ], + }), + ], + }); + ``` + +With this updated configuration, the search bar on your site will now open an Algolia modal instead of the default search modal. + +#### Translating the DocSearch UI + +DocSearch only provides English UI strings by default. +Add translations of the modal UI for your language using Starlight’s built-in [internationalization system](/guides/i18n/#translate-starlights-ui). + +1. Extend Starlight’s `i18n` content collection definition with the DocSearch schema in `src/content/config.ts`: + + ```js ins={4} ins=/{ extend: .+ }/ + // src/content/config.ts + import { defineCollection } from 'astro:content'; + import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + + export const collections = { + docs: defineCollection({ schema: docsSchema() }), + i18n: defineCollection({ + type: 'data', + schema: i18nSchema({ extend: docSearchI18nSchema() }), + }), + }; + ``` + +2. Add translations to your JSON files in `src/content/i18n/`. + + These are the English defaults used by DocSearch: + + ```json title="src/content/i18n/en.json" + { + "docsearch.searchBox.resetButtonTitle": "Clear the query", + "docsearch.searchBox.resetButtonAriaLabel": "Clear the query", + "docsearch.searchBox.cancelButtonText": "Cancel", + "docsearch.searchBox.cancelButtonAriaLabel": "Cancel", + + "docsearch.startScreen.recentSearchesTitle": "Recent", + "docsearch.startScreen.noRecentSearchesText": "No recent searches", + "docsearch.startScreen.saveRecentSearchButtonTitle": "Save this search", + "docsearch.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", + "docsearch.startScreen.favoriteSearchesTitle": "Favorite", + "docsearch.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + + "docsearch.errorScreen.titleText": "Unable to fetch results", + "docsearch.errorScreen.helpText": "You might want to check your network connection.", + + "docsearch.footer.selectText": "to select", + "docsearch.footer.selectKeyAriaLabel": "Enter key", + "docsearch.footer.navigateText": "to navigate", + "docsearch.footer.navigateUpKeyAriaLabel": "Arrow up", + "docsearch.footer.navigateDownKeyAriaLabel": "Arrow down", + "docsearch.footer.closeText": "to close", + "docsearch.footer.closeKeyAriaLabel": "Escape key", + "docsearch.footer.searchByText": "Search by", + + "docsearch.noResultsScreen.noResultsText": "No results for", + "docsearch.noResultsScreen.suggestedQueryText": "Try searching for", + "docsearch.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", + "docsearch.noResultsScreen.reportMissingResultsLinkText": "Let us know." + } + ``` diff --git a/packages/docsearch/DocSearch.astro b/packages/docsearch/DocSearch.astro new file mode 100644 index 0000000000..12db6b465b --- /dev/null +++ b/packages/docsearch/DocSearch.astro @@ -0,0 +1,139 @@ +--- +import type { Props } from '@astrojs/starlight/props'; +import '@docsearch/css/dist/modal.css'; +import type docsearch from '@docsearch/js'; +import './variables.css'; + +const { labels } = Astro.props; + +type DocSearchTranslationProps = Pick< + Parameters[0], + 'placeholder' | 'translations' +>; + +const pick = (keyStart: string) => + Object.fromEntries( + Object.entries(labels) + .filter(([key]) => key.startsWith(keyStart)) + .map(([key, value]) => [key.replace(keyStart, ''), value]) + ); + +const docsearchTranslations: DocSearchTranslationProps = { + placeholder: labels['search.label'], + translations: { + button: { buttonText: labels['search.label'], buttonAriaLabel: labels['search.label'] }, + modal: { + searchBox: pick('docsearch.searchBox.'), + startScreen: pick('docsearch.startScreen.'), + errorScreen: pick('docsearch.errorScreen.'), + footer: pick('docsearch.footer.'), + noResultsScreen: pick('docsearch.noResultsScreen.'), + }, + }, +}; +--- + + + + + + + + diff --git a/packages/docsearch/index.ts b/packages/docsearch/index.ts new file mode 100644 index 0000000000..eee4e04e43 --- /dev/null +++ b/packages/docsearch/index.ts @@ -0,0 +1,75 @@ +import type { StarlightPlugin } from '@astrojs/starlight/types'; +import type { AstroUserConfig, ViteUserConfig } from 'astro'; +import { z } from 'astro/zod'; + +/** Config options users must provide for DocSearch to work. */ +const DocSearchConfigSchema = z.object({ + appId: z.string(), + apiKey: z.string(), + indexName: z.string(), +}); +export type DocSearchConfig = z.input; + +/** Starlight DocSearch plugin. */ +export default function starlightDocSearch(userConfig: DocSearchConfig): StarlightPlugin { + const opts = DocSearchConfigSchema.parse(userConfig); + return { + name: 'starlight-docsearch', + hooks: { + setup({ addIntegration, config, logger, updateConfig }) { + // If the user has already has a custom override for the Search component, don't override it. + if (config.components?.Search) { + logger.warn( + 'It looks like you already have a `Search` component override in your Starlight configuration.' + ); + logger.warn( + 'To render `@astrojs/starlight-docsearch`, remove the override for the `Search` component.\n' + ); + } else { + // Otherwise, add the Search component override to the user's configuration. + updateConfig({ + pagefind: false, + components: { + ...config.components, + Search: '@astrojs/starlight-docsearch/DocSearch.astro', + }, + }); + } + + // Add an Astro integration that injects a Vite plugin to expose + // the DocSearch config via a virtual module. + addIntegration({ + name: 'starlight-docsearch', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + vite: { + plugins: [vitePluginDocSearch(opts)], + }, + } satisfies AstroUserConfig); + }, + }, + }); + }, + }, + }; +} + +/** Vite plugin that exposes the DocSearch config via virtual modules. */ +function vitePluginDocSearch(config: DocSearchConfig): VitePlugin { + const moduleId = 'virtual:starlight/docsearch-config'; + const resolvedModuleId = `\0${moduleId}`; + const moduleContent = `export default ${JSON.stringify(config)}`; + + return { + name: 'vite-plugin-starlight-docsearch-config', + load(id) { + return id === resolvedModuleId ? moduleContent : undefined; + }, + resolveId(id) { + return id === moduleId ? resolvedModuleId : undefined; + }, + }; +} + +type VitePlugin = NonNullable[number]; diff --git a/packages/docsearch/package.json b/packages/docsearch/package.json new file mode 100644 index 0000000000..68836a08eb --- /dev/null +++ b/packages/docsearch/package.json @@ -0,0 +1,34 @@ +{ + "name": "@astrojs/starlight-docsearch", + "version": "0.0.0", + "description": "Algolia DocSearch plugin for the Starlight documentation theme for Astro", + "author": "Chris Swithinbank ", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/withastro/starlight", + "directory": "packages/docsearch" + }, + "bugs": "https://github.com/withastro/starlight/issues", + "homepage": "https://starlight.astro.build", + "type": "module", + "files": [ + "index.ts", + "DocSearch.astro", + "schema.ts", + "variables.css", + "virtual.d.ts" + ], + "exports": { + ".": "./index.ts", + "./DocSearch.astro": "./DocSearch.astro", + "./schema": "./schema.ts" + }, + "peerDependencies": { + "@astrojs/starlight": ">=0.14.0" + }, + "dependencies": { + "@docsearch/css": "^3.5.2", + "@docsearch/js": "^3.5.2" + } +} diff --git a/packages/docsearch/schema.ts b/packages/docsearch/schema.ts new file mode 100644 index 0000000000..292e714a68 --- /dev/null +++ b/packages/docsearch/schema.ts @@ -0,0 +1,110 @@ +import { z } from 'astro/zod'; + +/** + * Schema for the Algolia DocSearch modal’s strings. + * + * Add this to your `src/content/config.ts`: + * + * ```js + * import { defineCollection } from 'astro:content'; + * import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + * import { docSearchI18nSchema } from '@astrojs/starlight-docsearch/schema'; + * + * export const collections = { + * docs: defineCollection({ schema: docsSchema() }), + * i18n: defineCollection({ + * type: 'data', + * schema: i18nSchema({ extend: docSearchI18nSchema() }), + * }), + * }; + * ``` + * + * DocSearch uses a nested object structure. + * This schema is a flattened version of DocSearch’s `modal` translations. + * + * For example, customizing DocSearch labels looks like this + * when using the component from JavaScript: + * + * ```js + * { + * modal: { + * footer: { + * selectKeyAriaLabel: 'Return key', + * }, + * }, + * }, + * ``` + * + * In your Starlight translation files, set this using the object path inside `modal` + * as the key for each string, prefixed with `docsearch`: + * + * ```json + * { + * "docsearch.footer.selectKeyAriaLabel": "Return key" + * } + * ``` + * + * @see https://docsearch.algolia.com/docs/api/#translations + */ +export const docSearchI18nSchema = () => + z + .object({ + // SEARCH BOX + /** Default: `Clear the query` */ + 'docsearch.searchBox.resetButtonTitle': z.string(), + /** Default: `Clear the query` */ + 'docsearch.searchBox.resetButtonAriaLabel': z.string(), + /** Default: `Cancel` */ + 'docsearch.searchBox.cancelButtonText': z.string(), + /** Default: `Cancel` */ + 'docsearch.searchBox.cancelButtonAriaLabel': z.string(), + + // START SCREEN + /** Default: `Recent` */ + 'docsearch.startScreen.recentSearchesTitle': z.string(), + /** Default: `No recent searches` */ + 'docsearch.startScreen.noRecentSearchesText': z.string(), + /** Default: `Save this search` */ + 'docsearch.startScreen.saveRecentSearchButtonTitle': z.string(), + /** Default: `Remove this search from history` */ + 'docsearch.startScreen.removeRecentSearchButtonTitle': z.string(), + /** Default: `Favorite` */ + 'docsearch.startScreen.favoriteSearchesTitle': z.string(), + /** Default: `Remove this search from favorites` */ + 'docsearch.startScreen.removeFavoriteSearchButtonTitle': z.string(), + + // ERROR SCREEN + /** Default: `Unable to fetch results` */ + 'docsearch.errorScreen.titleText': z.string(), + /** Default: `You might want to check your network connection.` */ + 'docsearch.errorScreen.helpText': z.string(), + + // FOOTER + /** Default: `to select` */ + 'docsearch.footer.selectText': z.string(), + /** Default: `Enter key` */ + 'docsearch.footer.selectKeyAriaLabel': z.string(), + /** Default: `to navigate` */ + 'docsearch.footer.navigateText': z.string(), + /** Default: `Arrow up` */ + 'docsearch.footer.navigateUpKeyAriaLabel': z.string(), + /** Default: `Arrow down` */ + 'docsearch.footer.navigateDownKeyAriaLabel': z.string(), + /** Default: `to close` */ + 'docsearch.footer.closeText': z.string(), + /** Default: `Escape key` */ + 'docsearch.footer.closeKeyAriaLabel': z.string(), + /** Default: `Search by` */ + 'docsearch.footer.searchByText': z.string(), + + // NO RESULTS SCREEN + /** Default: `No results for` */ + 'docsearch.noResultsScreen.noResultsText': z.string(), + /** Default: `Try searching for` */ + 'docsearch.noResultsScreen.suggestedQueryText': z.string(), + /** Default: `Believe this query should return results?` */ + 'docsearch.noResultsScreen.reportMissingResultsText': z.string(), + /** Default: `Let us know.` */ + 'docsearch.noResultsScreen.reportMissingResultsLinkText': z.string(), + }) + .partial(); diff --git a/packages/docsearch/variables.css b/packages/docsearch/variables.css new file mode 100644 index 0000000000..b1a0ebd665 --- /dev/null +++ b/packages/docsearch/variables.css @@ -0,0 +1,47 @@ +/* Variables */ +:root { + --docsearch-primary-color: var(--sl-color-text-accent); + --docsearch-text-color: var(--sl-color-text); + --docsearch-spacing: 12px; + --docsearch-icon-stroke-width: 1.4; + --docsearch-highlight-color: var(--docsearch-primary-color); + --docsearch-muted-color: var(--sl-color-gray-3); + --docsearch-container-background: var(--sl-color-backdrop-overlay); + + /* modal */ + --docsearch-modal-width: 560px; + --docsearch-modal-height: 600px; + --docsearch-modal-background: var(--sl-color-gray-6); + --docsearch-modal-shadow: var(--sl-shadow-lg); + + /* searchbox */ + --docsearch-searchbox-height: 56px; + --docsearch-searchbox-background: var(--sl-color-gray-7, var(--sl-color-gray-6)); + --docsearch-searchbox-focus-background: var(--sl-color-black); + --docsearch-searchbox-shadow: inset 0 0 0 1px var(--docsearch-primary-color); + + /* hit */ + --docsearch-hit-height: 56px; + --docsearch-hit-color: var(--sl-color-white); + --docsearch-hit-active-color: var(--sl-color-black); + --docsearch-hit-background: var(--sl-color-black); + + /* key */ + --docsearch-key-gradient: linear-gradient( + var(--sl-color-bg-inline-code) 0%, + var(--sl-color-bg-inline-code) 100% + ); + + /* footer */ + --docsearch-footer-height: 44px; + --docsearch-footer-background: var(--sl-color-black); + --docsearch-footer-shadow: 0 -1px 0 0 var(--sl-color-hairline-light); +} + +/* Custom style overrides */ +.DocSearch-Modal { + border: 1px solid var(--sl-color-hairline-light); +} +.DocSearch-Logo svg * { + fill: var(--docsearch-muted-color); +} diff --git a/packages/docsearch/virtual.d.ts b/packages/docsearch/virtual.d.ts new file mode 100644 index 0000000000..9723d98e39 --- /dev/null +++ b/packages/docsearch/virtual.d.ts @@ -0,0 +1,4 @@ +declare module 'virtual:starlight/docsearch-config' { + const DocSearchConfig: import('./index').DocSearchConfig; + export default DocSearchConfig; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 970560fd17..cff253ba7f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,6 +133,18 @@ importers: specifier: ^3.3.3 version: 3.3.3 + packages/docsearch: + dependencies: + '@astrojs/starlight': + specifier: '>=0.14.0' + version: link:../starlight + '@docsearch/css': + specifier: ^3.5.2 + version: 3.5.2 + '@docsearch/js': + specifier: ^3.5.2 + version: 3.5.2(@algolia/client-search@4.20.0)(search-insights@2.11.0) + packages/starlight: dependencies: '@astrojs/mdx': @@ -224,6 +236,140 @@ importers: packages: + /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.11.0): + resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.11.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + dev: false + + /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.11.0): + resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} + peerDependencies: + search-insights: '>= 1 < 3' + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + search-insights: 2.11.0 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + dev: false + + /@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0): + resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@algolia/client-search': 4.20.0 + algoliasearch: 4.20.0 + dev: false + + /@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0): + resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/client-search': 4.20.0 + algoliasearch: 4.20.0 + dev: false + + /@algolia/cache-browser-local-storage@4.20.0: + resolution: {integrity: sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==} + dependencies: + '@algolia/cache-common': 4.20.0 + dev: false + + /@algolia/cache-common@4.20.0: + resolution: {integrity: sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==} + dev: false + + /@algolia/cache-in-memory@4.20.0: + resolution: {integrity: sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==} + dependencies: + '@algolia/cache-common': 4.20.0 + dev: false + + /@algolia/client-account@4.20.0: + resolution: {integrity: sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==} + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + + /@algolia/client-analytics@4.20.0: + resolution: {integrity: sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==} + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + + /@algolia/client-common@4.20.0: + resolution: {integrity: sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==} + dependencies: + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + + /@algolia/client-personalization@4.20.0: + resolution: {integrity: sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==} + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + + /@algolia/client-search@4.20.0: + resolution: {integrity: sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==} + dependencies: + '@algolia/client-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + + /@algolia/logger-common@4.20.0: + resolution: {integrity: sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==} + dev: false + + /@algolia/logger-console@4.20.0: + resolution: {integrity: sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==} + dependencies: + '@algolia/logger-common': 4.20.0 + dev: false + + /@algolia/requester-browser-xhr@4.20.0: + resolution: {integrity: sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==} + dependencies: + '@algolia/requester-common': 4.20.0 + dev: false + + /@algolia/requester-common@4.20.0: + resolution: {integrity: sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==} + dev: false + + /@algolia/requester-node-http@4.20.0: + resolution: {integrity: sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==} + dependencies: + '@algolia/requester-common': 4.20.0 + dev: false + + /@algolia/transporter@4.20.0: + resolution: {integrity: sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==} + dependencies: + '@algolia/cache-common': 4.20.0 + '@algolia/logger-common': 4.20.0 + '@algolia/requester-common': 4.20.0 + dev: false + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -782,6 +928,49 @@ packages: engines: {node: '>=10'} dev: false + /@docsearch/css@3.5.2: + resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==} + dev: false + + /@docsearch/js@3.5.2(@algolia/client-search@4.20.0)(search-insights@2.11.0): + resolution: {integrity: sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==} + dependencies: + '@docsearch/react': 3.5.2(@algolia/client-search@4.20.0)(search-insights@2.11.0) + preact: 10.18.2 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + dev: false + + /@docsearch/react@3.5.2(@algolia/client-search@4.20.0)(search-insights@2.11.0): + resolution: {integrity: sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + dependencies: + '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.11.0) + '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@docsearch/css': 3.5.2 + algoliasearch: 4.20.0 + search-insights: 2.11.0 + transitivePeerDependencies: + - '@algolia/client-search' + dev: false + /@esbuild/android-arm64@0.18.17: resolution: {integrity: sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==} engines: {node: '>=12'} @@ -1624,6 +1813,25 @@ packages: - supports-color dev: true + /algoliasearch@4.20.0: + resolution: {integrity: sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==} + dependencies: + '@algolia/cache-browser-local-storage': 4.20.0 + '@algolia/cache-common': 4.20.0 + '@algolia/cache-in-memory': 4.20.0 + '@algolia/client-account': 4.20.0 + '@algolia/client-analytics': 4.20.0 + '@algolia/client-common': 4.20.0 + '@algolia/client-personalization': 4.20.0 + '@algolia/client-search': 4.20.0 + '@algolia/logger-common': 4.20.0 + '@algolia/logger-console': 4.20.0 + '@algolia/requester-browser-xhr': 4.20.0 + '@algolia/requester-common': 4.20.0 + '@algolia/requester-node-http': 4.20.0 + '@algolia/transporter': 4.20.0 + dev: false + /ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} dependencies: @@ -5218,6 +5426,10 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /preact@10.18.2: + resolution: {integrity: sha512-X/K43vocUHDg0XhWVmTTMbec4LT/iBMh+csCEqJk+pJqegaXsvjdqN80ZZ3L+93azWCnWCZ+WGwYb8SplxeNjA==} + dev: false + /prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} engines: {node: '>=10'} @@ -5677,6 +5889,10 @@ packages: /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + /search-insights@2.11.0: + resolution: {integrity: sha512-Uin2J8Bpm3xaZi9Y8QibSys6uJOFZ+REMrf42v20AA3FUDUrshKkMEP6liJbMAHCm71wO6ls4mwAf7a3gFVxLw==} + dev: false + /section-matter@1.0.0: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'}