From 0495e7192478606c0d499f768a8beedc0e8a7225 Mon Sep 17 00:00:00 2001 From: weareoutman Date: Fri, 30 Oct 2020 17:03:44 +0800 Subject: [PATCH] feat: search page to view all results --- package.json | 10 +- src/client/theme/SearchBar/SearchBar.css | 27 ++- src/client/theme/SearchBar/SearchBar.tsx | 22 ++- .../theme/SearchPage/SearchPage.module.css | 80 ++++++++ src/client/theme/SearchPage/SearchPage.tsx | 179 ++++++++++++++++++ src/client/theme/SearchPage/index.ts | 3 + src/client/theme/hooks/useSearchQuery.ts | 46 +++++ src/client/utils/smartQueries.spec.ts | 30 +++ src/declarations.ts | 25 ++- src/server/index.ts | 20 +- src/server/utils/parse.spec.ts | 2 + src/server/utils/parseDocument.spec.ts | 23 +++ src/server/utils/parseDocument.ts | 24 ++- src/server/utils/parsePage.spec.ts | 3 + src/server/utils/parsePage.ts | 1 + src/server/utils/processDocInfos.ts | 4 +- src/server/utils/scanDocuments.spec.ts | 8 + src/server/utils/scanDocuments.ts | 4 +- src/shared/interfaces.ts | 22 +++ tsconfig.json | 3 +- yarn.lock | 120 +++++++++++- 21 files changed, 626 insertions(+), 30 deletions(-) create mode 100644 src/client/theme/SearchPage/SearchPage.module.css create mode 100644 src/client/theme/SearchPage/SearchPage.tsx create mode 100644 src/client/theme/SearchPage/index.ts create mode 100644 src/client/theme/hooks/useSearchQuery.ts diff --git a/package.json b/package.json index 5f0642ad..b91fa04c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "npm run build:client && npm run build:server", "build:client": "tsc --project tsconfig.client.json", "build:server": "tsc --project tsconfig.server.json", - "postbuild": "copyfiles -f src/client/theme/SearchBar/SearchBar.css dist/client/client/theme/SearchBar", + "postbuild": "copyfiles -u 3 \"src/client/theme/**/*.css\" dist/client/client/theme", "release": "standard-version", "coveralls": "coveralls < .coverage/lcov.info" }, @@ -42,6 +42,9 @@ "@babel/preset-env": "^7.12.1", "@babel/preset-react": "^7.12.1", "@babel/preset-typescript": "^7.12.1", + "@docusaurus/module-type-aliases": "^2.0.0-alpha.66", + "@docusaurus/utils": "^2.0.0-alpha.66", + "@tsconfig/docusaurus": "^1.0.2", "@types/debug": "^4.1.5", "@types/enzyme": "^3.10.7", "@types/enzyme-adapter-react-16": "^1.0.6", @@ -50,8 +53,10 @@ "@types/jest": "^26.0.14", "@types/klaw-sync": "^6.0.0", "@types/lunr": "^2.3.3", - "@types/react": "^16.9.53", + "@types/react": "^16.9.55", "@types/react-dom": "^16.9.8", + "@types/react-helmet": "^6.1.0", + "@types/react-router-dom": "^5.1.6", "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.4.1", "babel-jest": "^26.5.2", @@ -75,6 +80,7 @@ "typescript": "^4.0.3" }, "peerDependencies": { + "@docusaurus/utils": "^2.0.0-alpha.66", "nodejieba": "^2.4.1" } } diff --git a/src/client/theme/SearchBar/SearchBar.css b/src/client/theme/SearchBar/SearchBar.css index 31808222..18108106 100644 --- a/src/client/theme/SearchBar/SearchBar.css +++ b/src/client/theme/SearchBar/SearchBar.css @@ -74,7 +74,8 @@ html[data-theme="dark"] .aa-dropdown-menu .aa-suggestion { .doc-search-hit-tree, .doc-search-hit-icon, .doc-search-hit-path, -.doc-search-empty-icon { +.doc-search-empty-icon, +.doc-search-hit-footer a { color: var(--search-local-muted-color, #969faf); } @@ -117,15 +118,19 @@ html[data-theme="dark"] .doc-search-empty-icon { .doc-search-hit-title { font-size: 0.9em; - white-space: nowrap; - overflow-x: hidden; - text-overflow: ellipsis; } .doc-search-hit-path { font-size: 0.75em; } +.doc-search-hit-path, +.doc-search-hit-title { + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; +} + .doc-search-hit-action { height: 20px; width: 20px; @@ -140,11 +145,21 @@ html[data-theme="dark"] .doc-search-empty-icon { flex-direction: column; align-items: center; justify-content: center; - padding: 12px 0; + padding: var(--search-local-spacing, 12px) 0; } .doc-search-empty-icon { - margin-bottom: 12px; + margin-bottom: var(--search-local-spacing, 12px); +} + +.doc-search-hit-footer { + text-align: center; + margin-top: var(--search-local-spacing, 12px); + font-size: 0.85em; +} + +.doc-search-hit-footer a { + text-decoration: underline; } .aa-cursor .doc-search-hit-action-icon { diff --git a/src/client/theme/SearchBar/SearchBar.tsx b/src/client/theme/SearchBar/SearchBar.tsx index b1d4825c..d04b80e4 100644 --- a/src/client/theme/SearchBar/SearchBar.tsx +++ b/src/client/theme/SearchBar/SearchBar.tsx @@ -1,7 +1,7 @@ import React, { ReactElement, useCallback, useRef, useState } from "react"; +import clsx from "clsx"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import { useHistory } from "@docusaurus/router"; -import clsx from "clsx"; import { fetchIndexes } from "./fetchIndexes"; import { SearchSourceFactory } from "../../utils/SearchSourceFactory"; import { SuggestionTemplate } from "../../utils/SuggestionTemplate.js"; @@ -67,6 +67,26 @@ export default function SearchBar({ templates: { suggestion: SuggestionTemplate, empty: EmptyTemplate, + footer: ({ query, isEmpty }: any) => { + if (isEmpty) { + return; + } + const a = document.createElement("a"); + const url = `${baseUrl}search?q=${encodeURIComponent(query)}`; + a.href = url; + a.textContent = "See all results"; + a.addEventListener("click", (e) => { + if (!e.ctrlKey && !e.metaKey) { + e.preventDefault(); + search.autocomplete.close(); + history.push(url); + } + }); + const div = document.createElement("div"); + div.className = "doc-search-hit-footer"; + div.appendChild(a); + return div; + }, }, }, ] diff --git a/src/client/theme/SearchPage/SearchPage.module.css b/src/client/theme/SearchPage/SearchPage.module.css new file mode 100644 index 00000000..874a3846 --- /dev/null +++ b/src/client/theme/SearchPage/SearchPage.module.css @@ -0,0 +1,80 @@ +.searchQueryInput { + border-radius: var(--ifm-global-radius); + border: var(--ifm-global-border-width) solid + var(--ifm-color-content-secondary); + font-size: var(--ifm-font-size-base); + padding: 0.5rem; + width: 100%; + background: #fff; + margin-bottom: 1rem; +} + +.searchResultItem { + padding: 1rem 0px; + border-bottom: 1px solid rgb(223, 227, 232); +} + +.searchResultItem > h2 { + margin-bottom: 0; +} + +.searchResultItemPath { + color: var(--ifm-color-content-secondary); + font-size: 0.8rem; + margin: 0.5rem 0px 0px; +} + +.searchResultItemSummary { + font-style: italic; + margin: 0.5rem 0px 0px; +} + +/* Start: pure CSS loaders */ +/* https://loading.io/css/ */ +.ldsRing { + display: inline-block; + position: absolute; + width: 20px; + height: 20px; + opacity: var(--search-local-loading-icon-opacity, 0.5); +} + +.ldsRing div { + box-sizing: border-box; + display: block; + position: absolute; + width: 16px; + height: 16px; + margin: 2px; + border: 2px solid + var(--search-load-loading-icon-color, var(--ifm-navbar-search-input-color)); + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: var( + --search-load-loading-icon-color, + var(--ifm-navbar-search-input-color) + ) + transparent transparent transparent; +} + +.ldsRing div:nth-child(1) { + animation-delay: -0.45s; +} + +.ldsRing div:nth-child(2) { + animation-delay: -0.3s; +} + +.ldsRing div:nth-child(3) { + animation-delay: -0.15s; +} + +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} +/* End: pure CSS loaders */ diff --git a/src/client/theme/SearchPage/SearchPage.tsx b/src/client/theme/SearchPage/SearchPage.tsx new file mode 100644 index 00000000..9e6bc4f9 --- /dev/null +++ b/src/client/theme/SearchPage/SearchPage.tsx @@ -0,0 +1,179 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import Layout from "@theme/Layout"; +import Head from "@docusaurus/Head"; +import Link from "@docusaurus/Link"; +import useSearchQuery from "../hooks/useSearchQuery"; + +import styles from "./SearchPage.module.css"; +import { fetchIndexes } from "../SearchBar/fetchIndexes"; +import { SearchSourceFactory } from "../../utils/SearchSourceFactory"; +import { SearchDocument, SearchResult } from "../../../shared/interfaces"; +import { highlight } from "../../utils/highlight"; +import { highlightStemmed } from "../../utils/highlightStemmed"; +import { getStemmedPositions } from "../../utils/getStemmedPositions"; + +export default function SearchPage(): React.ReactElement { + const { + siteConfig: { baseUrl }, + } = useDocusaurusContext(); + const { searchValue, updateSearchPath } = useSearchQuery(); + const [searchQuery, setSearchQuery] = useState(searchValue); + const [searchSource, setSearchSource] = useState< + (input: string, callback: (results: SearchResult[]) => void) => void + >(); + const [searchResults, setSearchResults] = useState(); + + const pageTitle = useMemo( + () => + searchQuery + ? `Search results for "${searchQuery}"` + : "Search the documentation", + [searchQuery] + ); + + useEffect(() => { + updateSearchPath(searchQuery); + + if (searchSource) { + if (searchQuery) { + searchSource(searchQuery, (results) => { + setSearchResults(results); + }); + } else { + setSearchResults(undefined); + } + } + + // `updateSearchPath` should not be in the deps, + // otherwise will cause call stack overflow. + }, [searchQuery, searchSource]); + + const handleSearchInputChange = useCallback((e) => { + setSearchQuery(e.target.value); + }, []); + + useEffect(() => { + if (searchValue && searchValue !== searchQuery) { + setSearchQuery(searchValue); + } + }, [searchValue]); + + useEffect(() => { + async function doFetchIndexes() { + const { wrappedIndexes, zhDictionary } = await fetchIndexes(baseUrl); + setSearchSource(() => + SearchSourceFactory(wrappedIndexes, zhDictionary, 100) + ); + } + doFetchIndexes(); + }, [baseUrl]); + + return ( + + + {/* + We should not index search pages + See https://github.com/facebook/docusaurus/pull/3233 + */} + + + +
+

{pageTitle}

+ +
+ +
+ + {!searchSource && searchQuery && ( +
+
+
+
+
+
+
+
+ )} + + {searchResults && + (searchResults.length > 0 ? ( +

+ {searchResults.length} document + {searchResults.length === 1 ? "" : "s"} found +

+ ) : ( +

No documents were found

+ ))} + +
+ {searchResults && + searchResults.map((item) => ( + + ))} +
+
+
+ ); +} + +function SearchResultItem({ + searchResult: { document, type, page, tokens, metadata }, +}: { + searchResult: SearchResult; +}): React.ReactElement { + const isTitle = type === 0; + const isContent = type === 2; + const pathItems = ((isTitle + ? document.b + : (page as SearchDocument).b) as string[]).slice(); + const articleTitle = (isContent ? document.s : document.t) as string; + if (!isTitle) { + pathItems.push((page as SearchDocument).t); + } + return ( +
+

+ +

+ {pathItems.length > 0 && ( +

{pathItems.join(" › ")}

+ )} + {isContent && ( +

+ )} +

+ ); +} diff --git a/src/client/theme/SearchPage/index.ts b/src/client/theme/SearchPage/index.ts new file mode 100644 index 00000000..b3b0558c --- /dev/null +++ b/src/client/theme/SearchPage/index.ts @@ -0,0 +1,3 @@ +import SearchPage from "./SearchPage"; + +export default SearchPage; diff --git a/src/client/theme/hooks/useSearchQuery.ts b/src/client/theme/hooks/useSearchQuery.ts new file mode 100644 index 00000000..e88d4d17 --- /dev/null +++ b/src/client/theme/hooks/useSearchQuery.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { useHistory, useLocation } from "@docusaurus/router"; +import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; + +const SEARCH_PARAM_QUERY = "q"; + +function useSearchQuery(): any { + const history = useHistory(); + const location = useLocation(); + const { + siteConfig: { baseUrl }, + } = useDocusaurusContext(); + + return { + searchValue: + (ExecutionEnvironment.canUseDOM && + new URLSearchParams(location.search).get(SEARCH_PARAM_QUERY)) || + "", + updateSearchPath: (searchValue: string) => { + const searchParams = new URLSearchParams(location.search); + + if (searchValue) { + searchParams.set(SEARCH_PARAM_QUERY, searchValue); + } else { + searchParams.delete(SEARCH_PARAM_QUERY); + } + + history.replace({ + search: searchParams.toString(), + }); + }, + generateSearchPageLink: (searchValue: string) => { + // Refer to https://github.com/facebook/docusaurus/pull/2838 + return `${baseUrl}search?q=${encodeURIComponent(searchValue)}`; + }, + }; +} + +export default useSearchQuery; diff --git a/src/client/utils/smartQueries.spec.ts b/src/client/utils/smartQueries.spec.ts index 161c5551..5d76a34f 100644 --- a/src/client/utils/smartQueries.spec.ts +++ b/src/client/utils/smartQueries.spec.ts @@ -173,6 +173,36 @@ describe("smartQueries", () => { }, ], ], + [ + ["hello", "a"], + [ + { + tokens: ["hello", "a"], + keyword: "+hello +a", + }, + { + tokens: ["hello"], + keyword: "+hello", + }, + { + tokens: ["hello", "a"], + keyword: "+hello +a*", + }, + ], + ], + [ + ["a"], + [ + { + tokens: ["a"], + keyword: "+a", + }, + { + tokens: ["a"], + keyword: "+a*", + }, + ], + ], [ ["hello", "world", "命"], [ diff --git a/src/declarations.ts b/src/declarations.ts index 6a3bd842..f42b239f 100644 --- a/src/declarations.ts +++ b/src/declarations.ts @@ -1,15 +1,22 @@ -declare module "@docusaurus/useDocusaurusContext" { - const useDocusaurusContext: () => { - siteConfig: { - baseUrl: string; - }; - }; - export default useDocusaurusContext; -} +// declare module "*.module.css" { +// const classes: { [key: string]: string }; +// export default classes; +// } + +// declare module "@docusaurus/useDocusaurusContext" { +// const useDocusaurusContext: () => { +// baseUrl: string; +// siteConfig: { +// baseUrl: string; +// }; +// }; +// export default useDocusaurusContext; +// } declare module "@docusaurus/router" { export const useHistory: () => { push: (url: string) => void; + replace: (args: any) => void; }; } @@ -27,3 +34,5 @@ declare module "*/generated.js" { export const __setLanguage: (value: string[]) => void; export const __setRemoveDefaultStopWordFilter: (value: boolean) => void; } + +declare module "@docusaurus/Head"; diff --git a/src/server/index.ts b/src/server/index.ts index 860ed3c5..17340d39 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,5 +1,6 @@ import path from "path"; import fs from "fs-extra"; +import { normalizeUrl } from "@docusaurus/utils"; import { DocusaurusContext, PluginOptions } from "../shared/interfaces"; import { processPluginOptions } from "./utils/processPluginOptions"; import { postBuildFactory } from "./utils/postBuildFactory"; @@ -17,12 +18,29 @@ export default function DocusaurusSearchLocalPlugin( fs.ensureDirSync(dir); generate(config, dir); + const themePage = path.resolve(__dirname, "../../client/client/theme"); + const pagePath = path.join(themePage, "SearchPage/index.js"); + return { name: PLUGIN_NAME, + getThemePath() { - return path.resolve(__dirname, "../../client/client/theme"); + return themePage; }, + postBuild: postBuildFactory(config), + + getPathsToWatch() { + return [pagePath]; + }, + + async contentLoaded({ actions: { addRoute } }: any) { + addRoute({ + path: normalizeUrl([context.baseUrl, "search"]), + component: pagePath, + exact: true, + }); + }, }; } diff --git a/src/server/utils/parse.spec.ts b/src/server/utils/parse.spec.ts index 5bfc90cc..5622607b 100644 --- a/src/server/utils/parse.spec.ts +++ b/src/server/utils/parse.spec.ts @@ -28,6 +28,7 @@ describe("parse", () => { content: "Peace. Code.", }, ], + breadcrumb: [], }, ], [ @@ -52,6 +53,7 @@ describe("parse", () => { content: "Peace.", }, ], + breadcrumb: [], }, ], ])("parse(...) should work", (html, type, doc) => { diff --git a/src/server/utils/parseDocument.spec.ts b/src/server/utils/parseDocument.spec.ts index 970502e8..8d3fd560 100644 --- a/src/server/utils/parseDocument.spec.ts +++ b/src/server/utils/parseDocument.spec.ts @@ -6,6 +6,27 @@ describe("parseDocument", () => { test.each<[string, ParsedDocument]>([ [ ` + +

Hello World

@@ -41,6 +62,7 @@ describe("parseDocument", () => { content: "", }, ], + breadcrumb: ["Docs", "Guide", "Advanced"], }, ], [ @@ -86,6 +108,7 @@ describe("parseDocument", () => { content: "", }, ], + breadcrumb: [], }, ], ])("parseDocument(...) should work", (html, doc) => { diff --git a/src/server/utils/parseDocument.ts b/src/server/utils/parseDocument.ts index 55be3e1b..ff7146c0 100644 --- a/src/server/utils/parseDocument.ts +++ b/src/server/utils/parseDocument.ts @@ -8,11 +8,29 @@ export function parseDocument($: cheerio.Root): ParsedDocument { const pageTitle = $pageTitle.text(); const sections: ParsedDocumentSection[] = []; + const breadcrumb: string[] = []; + + const navbarActiveItem = $(".navbar__link--active"); + if (navbarActiveItem.length > 0) { + breadcrumb.push(navbarActiveItem.eq(0).text().trim()); + } + + const menu = $(".main-wrapper .menu"); + // console.log("menu.length", menu.length); + if (menu.length > 0) { + const activeMenuItem = menu + .eq(0) + .find(".menu__link--sublist.menu__link--active"); + // console.log("activeMenuItem.length", activeMenuItem.length); + activeMenuItem.each((_, element) => { + breadcrumb.push($(element).text().trim()); + }); + } $("article") .find(HEADINGS) - .each((_, heading) => { - const $h = $(heading); + .each((_, element) => { + const $h = $(element); // Remove elements that are marked as aria-hidden. // This is mainly done to remove anchors like this: // @@ -42,5 +60,5 @@ export function parseDocument($: cheerio.Root): ParsedDocument { }); }); - return { pageTitle, sections }; + return { pageTitle, sections, breadcrumb }; } diff --git a/src/server/utils/parsePage.spec.ts b/src/server/utils/parsePage.spec.ts index 8be5bb26..f5693ae8 100644 --- a/src/server/utils/parsePage.spec.ts +++ b/src/server/utils/parsePage.spec.ts @@ -25,6 +25,7 @@ describe("parsePage", () => { content: "Peace.", }, ], + breadcrumb: [], }, ], [ @@ -46,6 +47,7 @@ describe("parsePage", () => { content: "Peace.", }, ], + breadcrumb: [], }, ], [ @@ -69,6 +71,7 @@ describe("parsePage", () => { content: "", }, ], + breadcrumb: [], }, ], ])("parsePage(...) should work", (html, url, doc) => { diff --git a/src/server/utils/parsePage.ts b/src/server/utils/parsePage.ts index e2c88f2b..be674039 100644 --- a/src/server/utils/parsePage.ts +++ b/src/server/utils/parsePage.ts @@ -30,5 +30,6 @@ export function parsePage($: cheerio.Root, url: string): ParsedDocument { $main.length > 0 ? getCondensedText($main.get(0), $).trim() : "", }, ], + breadcrumb: [], }; } diff --git a/src/server/utils/processDocInfos.ts b/src/server/utils/processDocInfos.ts index f784721c..9bd5a5f5 100644 --- a/src/server/utils/processDocInfos.ts +++ b/src/server/utils/processDocInfos.ts @@ -25,8 +25,8 @@ export function processDocInfos( ); } const route = url.substr(baseUrl.length); - if (route === "404.html") { - // Do not index error page. + if (route === "404.html" || route === "search/index.html") { + // Do not index error page and search page. return; } if (indexBlog && urlMatchesPrefix(route, blogRouteBasePath)) { diff --git a/src/server/utils/scanDocuments.spec.ts b/src/server/utils/scanDocuments.spec.ts index 14067235..7a953adc 100644 --- a/src/server/utils/scanDocuments.spec.ts +++ b/src/server/utils/scanDocuments.spec.ts @@ -47,6 +47,7 @@ describe("scanDocuments", () => { content: "First content.", }, ], + breadcrumb: ["Docs"], }; } else { return { @@ -58,6 +59,7 @@ describe("scanDocuments", () => { content: "", }, ], + breadcrumb: [], }; } }); @@ -66,11 +68,15 @@ describe("scanDocuments", () => { Array [ Array [ Object { + "b": Array [ + "Docs", + ], "i": 1, "t": "Hello First Docs", "u": "/1", }, Object { + "b": Array [], "i": 5, "t": "Hello First Page", "u": "/2", @@ -88,12 +94,14 @@ describe("scanDocuments", () => { Object { "i": 2, "p": 1, + "s": "Hello First Docs", "t": "Leading content.", "u": "/1", }, Object { "i": 4, "p": 1, + "s": "First heading", "t": "First content.", "u": "/1#first-heading", }, diff --git a/src/server/utils/scanDocuments.ts b/src/server/utils/scanDocuments.ts index 601042b4..b7e38877 100644 --- a/src/server/utils/scanDocuments.ts +++ b/src/server/utils/scanDocuments.ts @@ -30,7 +30,7 @@ export async function scanDocuments( ); const html = await readFileAsync(filePath, { encoding: "utf8" }); - const { pageTitle, sections } = parse(html, type, url); + const { pageTitle, sections, breadcrumb } = parse(html, type, url); const titleId = getNextDocId(); @@ -38,6 +38,7 @@ export async function scanDocuments( i: titleId, t: pageTitle, u: url, + b: breadcrumb, }); for (const section of sections) { @@ -54,6 +55,7 @@ export async function scanDocuments( contentDocuments.push({ i: getNextDocId(), t: section.content, + s: section.title || pageTitle, u: url + section.hash, p: titleId, }); diff --git a/src/shared/interfaces.ts b/src/shared/interfaces.ts index 3e67b05f..e921c5aa 100644 --- a/src/shared/interfaces.ts +++ b/src/shared/interfaces.ts @@ -60,6 +60,12 @@ export interface SearchDocument { /** Doc parent ID. */ p?: number; + + /** Doc breadcrumb. */ + b?: string[]; + + /** Doc section title */ + s?: string; } export type SearchDocumentType = 0 | 1 | 2; @@ -92,6 +98,7 @@ export interface WrappedIndex { export interface ParsedDocument { pageTitle: string; sections: ParsedDocumentSection[]; + breadcrumb: string[]; } export interface ParsedDocumentSection { @@ -125,8 +132,22 @@ export interface PluginOptions { docsDir?: string; blogDir?: string; removeDefaultStopWordFilter?: boolean; + searchResultLimits?: number; searchResultContextMaxLength?: number; + // searchInputPlaceholder?: string; + // searchNoResults?: string; + // searchSeeAllResults?: string; + // searchSeeAllResultsPlural?: string; + + // searchPageResultLimits?: number; + // searchPageResultContextMaxLength?: number; + // searchPageInputPlaceholder?: string; + // searchPageNoResults?: string; + // searchPageDefaultTitle?: string; + // searchPageTitleWithKeyword?: string; + // searchPageResultSummary?: string; + // searchPageResultSummaryPlural?: string; } export type ProcessedPluginOptions = Required< @@ -142,6 +163,7 @@ export interface PostBuildData { } export interface DocusaurusContext { + baseUrl: string; siteDir: string; generatedFilesDir: string; } diff --git a/tsconfig.json b/tsconfig.json index f718e4ef..f6f60f4b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,8 @@ "resolveJsonModule": true, "skipLibCheck": true, "sourceMap": false, - "strict": true + "strict": true, + "types": ["node", "@docusaurus/module-type-aliases"] }, "include": ["src"], "exclude": ["**/*.spec.ts"] diff --git a/yarn.lock b/yarn.lock index becb6fcb..e358f132 100644 --- a/yarn.lock +++ b/yarn.lock @@ -960,6 +960,23 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@docusaurus/module-type-aliases@^2.0.0-alpha.66": + version "2.0.0-alpha.66" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-alpha.66.tgz#204588d36a1685aae5695c0717b8eac5b01d7ee9" + integrity sha512-d3+fRhjHFl/7oCXgX3E6RbD0h+iHAKjJUnqDKwvEMjavy1EwSg5XjgyqSAUzDBWbABE3dGP5RT/khAfqt1PDXw== + +"@docusaurus/utils@^2.0.0-alpha.66": + version "2.0.0-alpha.66" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-alpha.66.tgz#ef679896e7d7e536cc8196cc303f5f2ced1f5ebb" + integrity sha512-47jGB+Z3YVM6Xf1hxyNbJLMmc1qoTLmfwSf7NseKSkpjucbc5Ueivr+oVYp5yWoZw5sT5bObmdJYfJoD/RrbOg== + dependencies: + escape-string-regexp "^2.0.0" + fs-extra "^8.1.0" + gray-matter "^4.0.2" + lodash.camelcase "^4.3.0" + lodash.kebabcase "^4.1.1" + resolve-pathname "^3.0.0" + "@eslint/eslintrc@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" @@ -1248,6 +1265,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@tsconfig/docusaurus@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-1.0.2.tgz#400ef146d3e7da2f78bf9749c943d123dce5fd97" + integrity sha512-x4rRVb346vjyym6QbeB1Tv01XXwhbkujOmvDmtf0bT20oc2gbDhbmwpskKqZ5Of2Q/Vk4jNk1WMiLsZdJ9t7Dw== + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.10" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.10.tgz#ca58fc195dd9734e77e57c6f2df565623636ab40" @@ -1327,6 +1349,11 @@ resolved "https://registry.yarnpkg.com/@types/hapi__joi/-/hapi__joi-17.1.6.tgz#b84663676aa9753c17183718338dd40ddcbd3754" integrity sha512-y3A1MzNC0FmzD5+ys59RziE1WqKrL13nxtJgrSzjoO7boue5B7zZD2nZLPwrSuUviFjpKFQtgHYSvhDGfIE4jA== +"@types/history@*": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -1416,10 +1443,34 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.9.53": - version "16.9.53" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23" - integrity sha512-4nW60Sd4L7+WMXH1D6jCdVftuW7j4Za6zdp6tJ33Rqv0nk1ZAmQKML9ZLD4H0dehA3FZxXR/GM8gXplf82oNGw== +"@types/react-helmet@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.0.tgz#af586ed685f4905e2adc7462d1d65ace52beee7a" + integrity sha512-PYRoU1XJFOzQ3BHvWL1T8iDNbRjdMDJMT5hFmZKGbsq09kbSqJy61uwEpTrbTNWDopVphUT34zUSVLK9pjsgYQ== + dependencies: + "@types/react" "*" + +"@types/react-router-dom@^5.1.6": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.6.tgz#07b14e7ab1893a837c8565634960dc398564b1fb" + integrity sha512-gjrxYqxz37zWEdMVvQtWPFMFj1dRDb4TGOcgyOfSXTrEXdF92L00WE3C471O3TV/RF1oskcStkXsOU0Ete4s/g== + dependencies: + "@types/history" "*" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.8" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.8.tgz#4614e5ba7559657438e17766bb95ef6ed6acc3fa" + integrity sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.55": + version "16.9.55" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.55.tgz#47078587f5bfe028a23b6b46c7b94ac0d436acff" + integrity sha512-6KLe6lkILeRwyyy7yG9rULKJ0sXplUsl98MGoCfpteXf9sPWFWWMknDcsvubcpaTdBuxtsLF6HDUwdApZL/xIg== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -3423,6 +3474,15 @@ fs-access@^1.0.1: dependencies: null-check "^1.0.0" +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" @@ -3637,6 +3697,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +gray-matter@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" + integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== + dependencies: + js-yaml "^3.11.0" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -4615,7 +4685,7 @@ jest@^26.5.3: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@^3.11.0, js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -4707,6 +4777,13 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" @@ -4890,6 +4967,11 @@ lodash._reinterpolate@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.escape@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" @@ -4910,6 +4992,11 @@ lodash.ismatch@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -6254,6 +6341,11 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -6387,6 +6479,14 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -6847,6 +6947,11 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -7222,6 +7327,11 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"