Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2): contextual search, dynamic Algolia facetFilters #3550

Merged
merged 10 commits into from
Oct 15, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ Object {
\\"version\\": \\"current\\"
}",
"version-current-metadata-prop-751.json": "{
\\"pluginId\\": \\"default\\",
\\"version\\": \\"current\\",
\\"label\\": \\"Next\\",
\\"isLast\\": true,
Expand Down Expand Up @@ -640,6 +641,7 @@ Object {
\\"sidebar\\": \\"version-1.0.0/community\\"
}",
"version-1-0-0-metadata-prop-608.json": "{
\\"pluginId\\": \\"community\\",
\\"version\\": \\"1.0.0\\",
\\"label\\": \\"1.0.0\\",
\\"isLast\\": true,
Expand All @@ -657,6 +659,7 @@ Object {
}
}",
"version-current-metadata-prop-751.json": "{
\\"pluginId\\": \\"community\\",
\\"version\\": \\"current\\",
\\"label\\": \\"Next\\",
\\"isLast\\": false,
Expand Down Expand Up @@ -1102,6 +1105,7 @@ Object {
\\"version\\": \\"withSlugs\\"
}",
"version-1-0-0-metadata-prop-608.json": "{
\\"pluginId\\": \\"default\\",
\\"version\\": \\"1.0.0\\",
\\"label\\": \\"1.0.0\\",
\\"isLast\\": false,
Expand Down Expand Up @@ -1145,6 +1149,7 @@ Object {
}
}",
"version-1-0-1-metadata-prop-e87.json": "{
\\"pluginId\\": \\"default\\",
\\"version\\": \\"1.0.1\\",
\\"label\\": \\"1.0.1\\",
\\"isLast\\": true,
Expand Down Expand Up @@ -1182,6 +1187,7 @@ Object {
}
}",
"version-current-metadata-prop-751.json": "{
\\"pluginId\\": \\"default\\",
\\"version\\": \\"current\\",
\\"label\\": \\"Next\\",
\\"isLast\\": false,
Expand Down Expand Up @@ -1219,6 +1225,7 @@ Object {
}
}",
"version-with-slugs-metadata-prop-2bf.json": "{
\\"pluginId\\": \\"default\\",
\\"version\\": \\"withSlugs\\",
\\"label\\": \\"withSlugs\\",
\\"isLast\\": false,
Expand Down
6 changes: 5 additions & 1 deletion packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,11 @@ export default function pluginContentDocs(
`${docuHash(
`version-${loadedVersion.versionName}-metadata-prop`,
)}.json`,
JSON.stringify(toVersionMetadataProp(loadedVersion), null, 2),
JSON.stringify(
toVersionMetadataProp(pluginId, loadedVersion),
null,
2,
),
);

addRoute({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare module '@docusaurus/plugin-content-docs-types' {
};

export type PropVersionMetadata = {
pluginId: string;
version: string;
label: string;
isLast: boolean;
Expand Down
2 changes: 2 additions & 0 deletions packages/docusaurus-plugin-content-docs/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ Available document ids=
}

export function toVersionMetadataProp(
pluginId: string,
loadedVersion: LoadedVersion,
): PropVersionMetadata {
return {
pluginId,
version: loadedVersion.versionName,
label: loadedVersion.versionLabel,
isLast: loadedVersion.isLast,
Expand Down
18 changes: 18 additions & 0 deletions packages/docusaurus-plugin-content-docs/src/theme/hooks/useDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
getActiveDocContext,
getDocVersionSuggestions,
GetActivePluginOptions,
ActivePlugin,
} from '../../client/docsClientUtils';

export const useAllDocsData = (): Record<string, GlobalPluginData> =>
Expand All @@ -33,6 +34,23 @@ export const useActivePlugin = (options: GetActivePluginOptions = {}) => {
return getActivePlugin(data, pathname, options);
};

export const useActivePluginAndVersion = (
options: GetActivePluginOptions = {},
):
| undefined
| {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined} => {
const activePlugin = useActivePlugin(options);
const {pathname} = useLocation();
if (activePlugin) {
const activeVersion = getActiveVersion(activePlugin.pluginData, pathname);
return {
activePlugin,
activeVersion,
};
}
return undefined;
};

// versions are returned ordered (most recent first)
export const useVersions = (pluginId: string | undefined): GlobalVersion[] => {
const data = useDocsData(pluginId);
Expand Down
82 changes: 30 additions & 52 deletions packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,76 +18,54 @@ import NotFound from '@theme/NotFound';
import type {DocumentRoute} from '@theme/DocItem';
import type {Props} from '@theme/DocPage';
import {matchPath} from '@docusaurus/router';
import Head from '@docusaurus/Head';

import styles from './styles.module.css';
import {docVersionSearchTag} from '../../utils/searchUtils';

type DocPageContentProps = {
readonly currentDocRoute: DocumentRoute;
readonly versionMetadata: PropVersionMetadata;
readonly children: ReactNode;
};

// This theme is not coupled to Algolia, but can we do something else?
// Note the last version is also indexed with "last", to avoid breaking search on new releases
// See https://github.com/facebook/docusaurus/issues/3391
function DocSearchVersionHeader({
version,
isLast,
}: {
version: string;
isLast: boolean;
}) {
const versions = isLast ? [version, 'latest'] : [version];
return (
<Head>
<meta
name="docsearch:version"
content={
// See https://github.com/facebook/docusaurus/issues/3391#issuecomment-685594160
versions.join(',')
}
/>
</Head>
);
}

function DocPageContent({
currentDocRoute,
versionMetadata,
children,
}: DocPageContentProps): JSX.Element {
const {siteConfig, isClient} = useDocusaurusContext();
const {permalinkToSidebar, docsSidebars, version, isLast} = versionMetadata;
const {pluginId, permalinkToSidebar, docsSidebars, version} = versionMetadata;
const sidebarName = permalinkToSidebar[currentDocRoute.path];
const sidebar = docsSidebars[sidebarName];
return (
<>
<DocSearchVersionHeader version={version} isLast={isLast} />
<Layout key={isClient}>
<div className={styles.docPage}>
{sidebar && (
<div className={styles.docSidebarContainer} role="complementary">
<DocSidebar
key={
// Reset sidebar state on sidebar changes
// See https://github.com/facebook/docusaurus/issues/3414
sidebarName
}
sidebar={sidebar}
path={currentDocRoute.path}
sidebarCollapsible={
siteConfig.themeConfig?.sidebarCollapsible ?? true
}
/>
</div>
)}
<main className={styles.docMainContainer}>
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</main>
</div>
</Layout>
</>
<Layout
key={isClient}
searchMetadatas={{
version,
tag: docVersionSearchTag(pluginId, version),
}}>
<div className={styles.docPage}>
{sidebar && (
<div className={styles.docSidebarContainer} role="complementary">
<DocSidebar
key={
// Reset sidebar state on sidebar changes
// See https://github.com/facebook/docusaurus/issues/3414
sidebarName
}
sidebar={sidebar}
path={currentDocRoute.path}
sidebarCollapsible={
siteConfig.themeConfig?.sidebarCollapsible ?? true
}
/>
</div>
)}
<main className={styles.docMainContainer}>
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</main>
</div>
</Layout>
);
}

Expand Down
87 changes: 7 additions & 80 deletions packages/docusaurus-theme-classic/src/theme/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,99 +7,26 @@

import React from 'react';
import clsx from 'clsx';
import Head from '@docusaurus/Head';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';

import ThemeProvider from '@theme/ThemeProvider';
import UserPreferencesProvider from '@theme/UserPreferencesProvider';
import AnnouncementBar from '@theme/AnnouncementBar';
import Navbar from '@theme/Navbar';
import Footer from '@theme/Footer';
import LayoutProviders from '@theme/LayoutProviders';
import LayoutHead from '@theme/LayoutHead';
import type {Props} from '@theme/Layout';

import './styles.css';
import DocsPreferredVersionContextProvider from '../../utils/docsPreferredVersion/DocsPreferredVersionProvider';

function Providers({children}) {
return (
<ThemeProvider>
<UserPreferencesProvider>
<DocsPreferredVersionContextProvider>
{children}
</DocsPreferredVersionContextProvider>
</UserPreferencesProvider>
</ThemeProvider>
);
}

function Layout(props: Props): JSX.Element {
const {siteConfig} = useDocusaurusContext();
const {
favicon,
title: siteTitle,
themeConfig: {image: defaultImage, metadatas},
url: siteUrl,
titleDelimiter,
} = siteConfig;
const {
children,
title,
noFooter,
description,
image,
keywords,
permalink,
wrapperClassName,
} = props;
const metaTitle = title
? `${title} ${titleDelimiter} ${siteTitle}`
: siteTitle;
const metaImage = image || defaultImage;
const metaImageUrl = useBaseUrl(metaImage, {absolute: true});
const faviconUrl = useBaseUrl(favicon);
const {children, noFooter, wrapperClassName} = props;
return (
<Providers>
<Head>
{/* TODO: Do not assume that it is in english language */}
<html lang="en" />
{metaTitle && <title>{metaTitle}</title>}
{metaTitle && <meta property="og:title" content={metaTitle} />}
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
{keywords && keywords.length && (
<meta name="keywords" content={keywords.join(',')} />
)}
{metaImage && <meta property="og:image" content={metaImageUrl} />}
{metaImage && <meta property="twitter:image" content={metaImageUrl} />}
{metaImage && (
<meta name="twitter:image:alt" content={`Image for ${metaTitle}`} />
)}
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
{permalink && <link rel="canonical" href={siteUrl + permalink} />}
<meta name="twitter:card" content="summary_large_image" />
</Head>

<Head
// it's important to have an additional <Head> element here,
// as it allows react-helmet to override values set in previous <Head>
// ie we can override default metadatas such as "twitter:card"
// In same Head, the same meta would appear twice instead of overriding
// See react-helmet doc
>
{metadatas.map((metadata, i) => (
<meta key={`metadata_${i}`} {...metadata} />
))}
</Head>
<LayoutProviders>
<LayoutHead {...props} />

<AnnouncementBar />
<Navbar />
<div className={clsx('main-wrapper', wrapperClassName)}>{children}</div>

{!noFooter && <Footer />}
</Providers>
</LayoutProviders>
);
}

Expand Down
Loading