Skip to content

Commit

Permalink
Create a custom Algolia search for docs (#4100)
Browse files Browse the repository at this point in the history
* Update algolia search to use custom index

* Update naming of SearchItem

* sourceId is products

* Change sitemap domain back to docs.amplify.aws

* Remove old docsearch

* Remove default options if query is empty

* Increase hits per page

* Revert "Increase hits per page"

This reverts commit b48b318.

* Fix content error in headless.mdx

* Fix content error in workflows.mdx

* Fix content issues in cli/graphql/overview.mdx

* Fix url in cli/restapi/testing.mdx

* Fix content issues in commands.mdx

* Fix angle brackets in files.mdx

* Remove comment in export-to-cdk

* Fix files.mdx

* Fix example url to be code string in cli/usage/containers.mdx

* Use html entity characters in cli/teams/commands.mdx

* Remove comments from cli/function/build-options.mdx

* Fix transformer-migration.mdx

* Use html entity characters in cli/start/workflows.mdx

Co-authored-by: Tim Nguyen <timngyn@amazon.com>
  • Loading branch information
jakeburden and timngyn-amzn authored Apr 14, 2022
1 parent 857b165 commit b296f22
Show file tree
Hide file tree
Showing 42 changed files with 5,527 additions and 4,399 deletions.
28 changes: 28 additions & 0 deletions adobe.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
interface AdobeS {
// Configuration properties
trackExternalLinks: boolean;

// Variables to set when tracking
linkTrackVars: string;
linkTrackEvents: string;
events: string;
pageURL: string;
eVar26: string;
eVar27: string;

// Tracking functions
t: () => void;
tl: (
linkObject: true | undefined,
linkType: string,
linkName: string
) => void;
}

interface AWSCShortbreadObject {
checkForCookieConsent: () => void;
}

declare const s: AdobeS;
declare const docsearch: (obj: object) => void;
declare const AWSCShortbread: (obj: object) => AWSCShortbreadObject;
3 changes: 2 additions & 1 deletion amplify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ frontend:
build:
commands:
- NODE_ENV=production yarn build
- node tasks/build-algolia-search.mjs
artifacts:
# IMPORTANT - Please verify your build output directory
baseDirectory: /client/www/next-build
files:
- "**/*"
- '**/*'
cache:
paths:
- node_modules/**/*
32 changes: 3 additions & 29 deletions next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,5 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />

interface AdobeS {
// Configuration properties
trackExternalLinks: boolean;

// Variables to set when tracking
linkTrackVars: string;
linkTrackEvents: string;
events: string;
pageURL: string;
eVar26: string;
eVar27: string;

// Tracking functions
t: () => void;
tl: (
linkObject: true | undefined,
linkType: string,
linkName: string,
) => void;
}

interface AWSCShortbreadObject {
checkForCookieConsent: () => void;
}

declare const s: AdobeS;
declare const docsearch: (obj: object) => void;
declare const AWSCShortbread: (obj: object) => AWSCShortbreadObject;
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
95 changes: 53 additions & 42 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,64 @@
const withTM = require('next-transpile-modules')([
'@algolia/autocomplete-shared'
]); // pass the modules you would like to see transpiled

const mdxRenderer = `
import { mdx } from "@mdx-js/react";
`;

// eslint-disable-next-line @typescript-eslint/no-var-requires
const directory = require("./src/directory/directory.js");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const headingLinkPlugin = require("./src/plugins/headings.tsx");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pagePlugin = require("./src/plugins/page.tsx");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const importPlugin = require("./src/plugins/import.tsx");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const codeBlockPlugin = require("./src/plugins/code-block.tsx");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const internalLinkPlugin = require("./src/plugins/internal-link.tsx");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withMDX = require("@next/mdx")({
extension: /\.mdx$/,
options: {
remarkPlugins: [
importPlugin,
headingLinkPlugin,
pagePlugin,
internalLinkPlugin,
],
rehypePlugins: [codeBlockPlugin],
renderer: mdxRenderer,
},
});

module.exports = withMDX({
pageExtensions: ["js", "jsx", "mdx", "tsx", "ts"],
typescript: {
// !! WARN !!
// Dangerously allow production builds to successfully complete even if
// your project has type errors.
// !! WARN !!
ignoreBuildErrors: true,
},
future: {
webpack5: true,
},
exportPathMap,
trailingSlash: true,
});
const directory = require('./src/directory/directory.js');

module.exports = async (phase, { defaultConfig }) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const headingLinkPlugin = await require('./src/plugins/headings.tsx');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pagePlugin = await require('./src/plugins/page.tsx');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const internalLinkPlugin = await require('./src/plugins/internal-link.tsx');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const codeBlockPlugin = await require('./src/plugins/code-block.tsx');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const importPlugin = await require('./src/plugins/import.tsx');

const withMDX = require('@next/mdx')({
extension: /\.mdx$/,
options: {
remarkPlugins: [
importPlugin,
headingLinkPlugin,
pagePlugin,
internalLinkPlugin
],
rehypePlugins: [codeBlockPlugin],
renderer: mdxRenderer
}
});

const nextConfig = withTM(
withMDX({
pageExtensions: ['js', 'jsx', 'mdx', 'tsx', 'ts'],
typescript: {
// !! WARN !!
// Dangerously allow production builds to successfully complete even if
// your project has type errors.
// !! WARN !!
ignoreBuildErrors: true
},
future: {
webpack5: true
},
exportPathMap,
trailingSlash: true
})
);

return nextConfig;
};

// eslint-disable-next-line @typescript-eslint/no-var-requires
const generatePathMap = require("./generatePathMap.cjs");
const generatePathMap = require('./generatePathMap.cjs');
function exportPathMap(defaultPathMap, props) {
return generatePathMap(directory);
}
27 changes: 23 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,40 @@
"capi"
],
"dependencies": {
"@algolia/autocomplete-js": "^1.5.3",
"@algolia/autocomplete-plugin-query-suggestions": "^1.5.6",
"@algolia/autocomplete-plugin-recent-searches": "^1.5.6",
"@algolia/autocomplete-shared": "^1.5.6",
"@algolia/autocomplete-theme-classic": "^1.6.1",
"@algolia/client-search": "^4.13.0",
"@aws-amplify/ui-components": "latest",
"@aws-amplify/ui-react": "^1.2.5",
"@emotion/react": "^11.1.5",
"@emotion/styled": "^11.3.0",
"@mdx-js/mdx": "^2.0.0",
"algoliasearch": "^4.12.1",
"array-flatten": "^3.0.0",
"aws-amplify": "latest",
"copy-to-clipboard": "^3.2.1",
"dotenv": "^16.0.0",
"emotion": "^10.0.23",
"extract-mdx-metadata": "^2.0.0",
"html-entities": "^1.2.1",
"next": "^10.2.0",
"instantsearch.js": "^4.39.1",
"next": "^12.1.4",
"next-transpile-modules": "^9.0.0",
"parse-imports": "^1.1.0",
"prismjs": "^1.21.0",
"ramda": "^0.28.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"rehype": "^11.0.0",
"theme-ui": "^0.7.5"
"remark": "^14.0.2",
"remark-mdx": "^2.0.0",
"remark-mdx-searchable": "^0.1.3",
"theme-ui": "^0.7.5",
"unified": "^10.1.2",
"unist-util-visit": "^4.1.0"
},
"devDependencies": {
"@mdx-js/loader": "^1.6.22",
Expand Down Expand Up @@ -90,8 +109,8 @@
"spellcheck": "cspell 'src/**/*.mdx'",
"spellcheck-diff": "cspell --no-must-find-files $(git diff --cached --name-only | awk '/src.*\\.mdx/{print}' | cat - <(echo 'preventNoFilesPrintout'))",
"dev": "next dev",
"build": "yarn task patch-next-scrolling && yarn task generate-sitemap && next build && next export -o client/www/next-build",
"build": "yarn task generate-sitemap && next build && next export -o client/www/next-build",
"next-build": "next build",
"next-start": "next start"
}
}
}
2 changes: 0 additions & 2 deletions public/scripts/docsearchv2_6_3.js

This file was deleted.

34 changes: 17 additions & 17 deletions src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import Head from "next/head";
import UniversalNav from "../UniversalNav/index";
import SecondaryNav from "../SecondaryNav/index";
import Footer from "../Footer/index";
import {LayoutStyle} from "./styles";
import {Container} from "../Container";
import {useRouter} from "next/router";
import Head from 'next/head';
import UniversalNav from '../UniversalNav/index';
import SecondaryNav from '../SecondaryNav/index';
import Footer from '../Footer/index';
import { LayoutStyle } from './styles';
import { Container } from '../Container';
import { useRouter } from 'next/router';

export default function Layout({
children,
meta,
filterKey,
filterMetadataByOption,
filterMetadataByOption
}: {
children: any;
meta?: any;
Expand All @@ -22,19 +22,19 @@ export default function Layout({

const filterMetadata = filterKey
? filterMetadataByOption[filterKey].label
: "";
: '';

const title = !meta
? ""
: [meta.chapterTitle, meta.title, filterMetadata, "AWS Amplify Docs"]
.filter((s) => s !== "")
.join(" - ");
? ''
: [meta.chapterTitle, meta.title, filterMetadata, 'AWS Amplify Docs']
.filter((s) => s !== '')
.join(' - ');

const description = !meta
? ""
: [meta.description, filterMetadata, "AWS Amplify Docs"]
.filter((s) => s !== "")
.join(" - ");
? ''
: [meta.description, filterMetadata, 'AWS Amplify Docs']
.filter((s) => s !== '')
.join(' - ');

return (
<>
Expand Down
101 changes: 101 additions & 0 deletions src/components/SearchBar/Autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { autocomplete } from '@algolia/autocomplete-js';
import { createQuerySuggestionsPlugin } from '@algolia/autocomplete-plugin-query-suggestions';
import { createLocalStorageRecentSearchesPlugin } from '@algolia/autocomplete-plugin-recent-searches';
import algoliasearch from 'algoliasearch';

import React, { createElement, Fragment, useEffect, useRef } from 'react';
import { render } from 'react-dom';

import { pipe } from 'ramda';

import { groupBy, limit, uniqBy } from './functions/index';

const appId = 'W6Q5N5WUDV';
const apiKey = 'a82ff7ed9cd894525d84229ba4a886db';
const searchClient = algoliasearch(appId, apiKey);

const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
key: 'search',
limit: 20
});
const querySuggestionsPlugin = createQuerySuggestionsPlugin({
searchClient,
indexName: 'custom_search_staging',
getSearchParams() {
return {
hitsPerPage: 20
};
}
});

const dedupeAndLimitSuggestions = pipe(
uniqBy(({ source, item }) =>
source.sourceId === 'querySuggestionsPlugin' ? item.query : item.title
),
limit(10)
);

const groupByCategory = groupBy((hit) => hit.category, {
getSource({ name, items }) {
return {
getItems() {
return items;
},
templates: {
header() {
return (
<>
<span className="aa-SourceHeaderTitle">{name}</span>
<div className="aa-SourceHeaderLine" />
</>
);
}
}
};
}
});

export function Autocomplete(props) {
const containerRef = useRef(null);

useEffect(() => {
if (!containerRef.current) {
return undefined;
}

const search = autocomplete({
container: containerRef.current,
renderer: { createElement, Fragment },
plugins: [recentSearchesPlugin, querySuggestionsPlugin],
getSources({ query }) {
if (!query) {
return [];
}
},
reshape({ sourcesBySourceId }) {
const {
recentSearchesPlugin,
querySuggestionsPlugin,
products,
...rest
} = sourcesBySourceId;

return [
dedupeAndLimitSuggestions(),
groupByCategory(products),
Object.values(rest)
];
},
render({ children }, root) {
render(children, root);
},
...props
});

return () => {
search.destroy();
};
}, [props]);

return <div ref={containerRef} />;
}
Loading

0 comments on commit b296f22

Please sign in to comment.