From 27058df154df94062880986d08b4563187918abf Mon Sep 17 00:00:00 2001 From: Herbert Nikolajewski Date: Mon, 9 Dec 2024 12:49:39 +0100 Subject: [PATCH] feat: Add option to filter search results by url/pathname --- README.md | 10 ++++++++ .../src/client/theme/SearchBar/index.tsx | 23 +++++++++++++++---- .../src/server/index.test.js | 4 ++++ .../src/server/index.ts | 10 ++++++++ packages/docusaurus-search-local/src/types.ts | 2 ++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1599ae8..76cde15 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,16 @@ The following options are available (defaults are shown below): // searches, but simply does not display additional search results that have been found. maxSearchResults: 8, + // This option allows restricting search context to the current URL. + filterByPathName: false, + + // This option only works if filterByPathName is set to true. It allows further filtering of the search context. + // Example: Suppose this is our endpoint: "/help/page1/subpage1/topic". If I set subPath: 2, then the search context + // will be limited to everything that can be found under help/page1/*. Anything that's under /help/page3 or similar + // will be filtered out. subPath: 3 => then only help/page1/subpage1/* not help/page1/subpage2/*, etc. + // The default value is set to -1, which always allows searching the current page only as search context. + subPath: -1, + // lunr.js-specific settings lunr: { // When indexing your documents, their content is split into "tokens". diff --git a/packages/docusaurus-search-local/src/client/theme/SearchBar/index.tsx b/packages/docusaurus-search-local/src/client/theme/SearchBar/index.tsx index 8683f67..707fd6e 100644 --- a/packages/docusaurus-search-local/src/client/theme/SearchBar/index.tsx +++ b/packages/docusaurus-search-local/src/client/theme/SearchBar/index.tsx @@ -114,6 +114,8 @@ const SearchBar = () => { parentCategoriesBoost, indexDocSidebarParentCategories, maxSearchResults, + filterByPathName, + subPath, } = usePluginData("@cmfcmf/docusaurus-search-local") as DSLAPluginData; const history = useHistory(); @@ -310,8 +312,8 @@ const SearchBar = () => { const terms = tokenize(input); return indexes - .flatMap(({ index, documents }) => - index + .flatMap(({ index, documents }) => { + const queriedIndex = index .query((query) => { query.term(terms, { fields: ["title"], @@ -360,8 +362,21 @@ const SearchBar = () => { )!, score: result.score, terms, - })), - ) + })); + + if (filterByPathName) { + const pathNameArray = window.location.pathname.split("/"); + const pathNamePart = + pathNameArray[ + subPath === -1 ? pathNameArray.length - 1 : subPath + ]; + return queriedIndex.filter((item) => + item.document.sectionRoute.includes(pathNamePart), + ); + } + + return queriedIndex; + }) .sort((a, b) => b.score - a.score) .slice(0, maxSearchResults); }, diff --git a/packages/docusaurus-search-local/src/server/index.test.js b/packages/docusaurus-search-local/src/server/index.test.js index 74e4117..075cbef 100644 --- a/packages/docusaurus-search-local/src/server/index.test.js +++ b/packages/docusaurus-search-local/src/server/index.test.js @@ -17,6 +17,8 @@ const DEFAULT_OPTIONS = { language: "en", style: undefined, maxSearchResults: 8, + filterByPathName: false, + subPath: -1, lunr: { tokenizerSeparator: undefined, b: 0.75, @@ -64,6 +66,8 @@ it("validates options correctly", () => { language: "hi", style: "none", maxSearchResults: 123, + filterByPathName: false, + subPath: -1, lunr: { tokenizerSeparator: /-+/, b: 0.6, diff --git a/packages/docusaurus-search-local/src/server/index.ts b/packages/docusaurus-search-local/src/server/index.ts index d03c878..b502171 100644 --- a/packages/docusaurus-search-local/src/server/index.ts +++ b/packages/docusaurus-search-local/src/server/index.ts @@ -82,6 +82,8 @@ type MyOptions = { language: string | string[]; style?: "none"; maxSearchResults: number; + filterByPathName: boolean; + subPath: number; lunr: { tokenizerSeparator?: string; k1: number; @@ -140,6 +142,10 @@ const optionsSchema = Joi.object({ maxSearchResults: Joi.number().integer().min(1).default(8), + filterByPathName: Joi.boolean().default(false), + + subPath: Joi.number().integer().min(-1).default(-1), + lunr: Joi.object({ tokenizerSeparator: Joi.object().regex(), b: Joi.number().min(0).max(1).default(0.75), @@ -164,6 +170,8 @@ export default function cmfcmfDocusaurusSearchLocal( language, style, maxSearchResults, + filterByPathName, + subPath, lunr: { tokenizerSeparator: lunrTokenizerSeparator, k1, @@ -300,6 +308,8 @@ export const tokenize = (input) => lunr.tokenizer(input) parentCategoriesBoost, indexDocSidebarParentCategories, maxSearchResults, + filterByPathName, + subPath, }; setGlobalData(data); }, diff --git a/packages/docusaurus-search-local/src/types.ts b/packages/docusaurus-search-local/src/types.ts index 0d6ea67..07871f3 100644 --- a/packages/docusaurus-search-local/src/types.ts +++ b/packages/docusaurus-search-local/src/types.ts @@ -5,6 +5,8 @@ export type DSLAPluginData = { tagsBoost: number; parentCategoriesBoost: number; maxSearchResults: number; + filterByPathName: boolean; + subPath: number; }; export type MyDocument = {