diff --git a/README.md b/README.md
index 1557abe6..1a58e32d 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,15 @@
+# How to restrict access to an _article_ or _category_:
+
+1. add `restrictedAccessHref` custom prop in `_category_.json` or article header
+ _value should be uniq across all docs_
+2. add full route to `config/restrictedAccessRoutes.json`
+ _to exclude it from search_
+
+
+
# How to translate a new article
There is a couple of pathes for each translated file:
diff --git a/config/restrictedAccessRoutes.json b/config/restrictedAccessRoutes.json
new file mode 100644
index 00000000..bb428d55
--- /dev/null
+++ b/config/restrictedAccessRoutes.json
@@ -0,0 +1 @@
+["/ecom/", "/automations/automations-by-event/welcome-series"]
diff --git a/config/searchExcludeRoutes.json b/config/searchExcludeRoutes.json
index d02c25ee..aabec3d8 100644
--- a/config/searchExcludeRoutes.json
+++ b/config/searchExcludeRoutes.json
@@ -1 +1 @@
-["/exclude-from-search/**", "/ecom/**"]
+["/exclude-from-search/**"]
diff --git a/docs/automations/automations-by-event/welcome-series.md b/docs/automations/automations-by-event/welcome-series.md
index c53c57fa..e15c934b 100644
--- a/docs/automations/automations-by-event/welcome-series.md
+++ b/docs/automations/automations-by-event/welcome-series.md
@@ -1,5 +1,6 @@
---
sidebar_position: 2
+sidebar_custom_props: { restrictedAccessHref: 'automations-by-event/welcome-series' }
---
# Как настроить приветственную серию писем
diff --git a/docs/ecom/_category_.json b/docs/ecom/_category_.json
index a95db8da..c107a584 100644
--- a/docs/ecom/_category_.json
+++ b/docs/ecom/_category_.json
@@ -1,6 +1,10 @@
{
"label": "Продажи",
"position": 14,
+ "link": {
+ "type": "generated-index",
+ "slug": "ecom"
+ },
"customProps": {
"restrictedAccessHref": "ecom"
}
diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js
index 2603b9f9..b32eca44 100644
--- a/src/theme/SearchBar/index.js
+++ b/src/theme/SearchBar/index.js
@@ -5,6 +5,8 @@ import { translate } from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { usePluginData } from '@docusaurus/useGlobalData';
import useIsBrowser from '@docusaurus/useIsBrowser';
+import { filterSearchExcludeOptions } from '../utils/filterSearchExcludeOptions';
+
const Search = (props) => {
const initialized = useRef(false);
const searchBarRef = useRef(null);
@@ -54,10 +56,19 @@ const Search = (props) => {
import('./DocSearch'),
import('./algolia.css'),
]).then(([searchDocs, searchIndex, { default: DocSearch }]) => {
- if (searchDocs.length === 0) {
+ const filteredSearchDocs = filterSearchExcludeOptions(searchDocs, isBrowser);
+ console.log(
+ '!!filteredSearchDocs',
+ searchDocs.length,
+ filteredSearchDocs.length,
+ searchIndex
+ );
+
+ if (filteredSearchDocs.length === 0) {
return;
}
- initAlgolia(searchDocs, searchIndex, DocSearch);
+
+ initAlgolia(filteredSearchDocs, searchIndex, DocSearch);
setIndexReady(true);
});
initialized.current = true;
diff --git a/src/theme/SearchBar/lunar-search.js b/src/theme/SearchBar/lunar-search.js
index c497c2e1..50fcb733 100644
--- a/src/theme/SearchBar/lunar-search.js
+++ b/src/theme/SearchBar/lunar-search.js
@@ -51,15 +51,20 @@ class LunrSearchAdapter {
};
}
getTitleHit(doc, position, length) {
- const start = position[0];
- const end = position[0] + length;
- let formattedTitle =
- doc.title.substring(0, start) +
- '' +
- doc.title.substring(start, end) +
- '' +
- doc.title.substring(end, doc.title.length);
- return this.getHit(doc, formattedTitle);
+ try {
+ const start = position[0];
+ const end = position[0] + length;
+ let formattedTitle =
+ doc.title.substring(0, start) +
+ '' +
+ doc.title.substring(start, end) +
+ '' +
+ doc.title.substring(end, doc.title.length);
+
+ return this.getHit(doc, formattedTitle);
+ } catch (err) {
+ console.log('!!err', doc, position, length);
+ }
}
getKeywordHit(doc, position, length) {
diff --git a/src/theme/hooks/useResctrictedPath.ts b/src/theme/hooks/useResctrictedPath.ts
index 81f26c69..d83748be 100644
--- a/src/theme/hooks/useResctrictedPath.ts
+++ b/src/theme/hooks/useResctrictedPath.ts
@@ -2,20 +2,23 @@ import { useLayoutEffect } from 'react';
import { PropSidebarItem } from '@docusaurus/plugin-content-docs';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { checkAllowedRoutes, ResctrictedAccessStorage, checkHiddenSidebarItem } from '../utils';
-import { RestrictedHref } from '../types';
+import { RestrictedHref, PropSidebarItemType } from '../types';
import { useRouteAllowance } from './useRouteAllowance';
export const useResctrictedPath = (item: PropSidebarItem) => {
- const isBrowser = useIsBrowser();
+ const isStorageAllowed = useIsBrowser();
const routeHref = item.customProps?.restrictedAccessHref as RestrictedHref;
- const { allowedRoutes, isNewAccessToRoute } = useRouteAllowance(routeHref, isBrowser);
+ const { allowedRoutes, isNewAccessToRoute } = useRouteAllowance(routeHref, {
+ isStorageAllowed,
+ type: item.type as PropSidebarItemType,
+ });
useLayoutEffect(() => {
- if (isNewAccessToRoute && isBrowser) {
+ if (isNewAccessToRoute && isStorageAllowed) {
ResctrictedAccessStorage.setJSON(allowedRoutes);
}
- }, [isBrowser]);
+ }, [isStorageAllowed, isNewAccessToRoute]);
return {
isRestricted: checkHiddenSidebarItem(item) || !checkAllowedRoutes(allowedRoutes, routeHref),
diff --git a/src/theme/hooks/useRouteAllowance.ts b/src/theme/hooks/useRouteAllowance.ts
index 02d86c01..99d54705 100644
--- a/src/theme/hooks/useRouteAllowance.ts
+++ b/src/theme/hooks/useRouteAllowance.ts
@@ -1,16 +1,17 @@
import { useHistory } from '@docusaurus/router';
import { checkNewAccessToRoute, getAllowedRoutes } from '../utils';
-import { RestrictedHref } from '../types';
+import { RestrictedHref, AllowedRoutesOptions } from '../types';
-export const useRouteAllowance = (routeHref: RestrictedHref, isStorageAllowed: boolean) => {
+export const useRouteAllowance = (newRouteHref: RestrictedHref, options: AllowedRoutesOptions) => {
const {
location: { pathname: path },
} = useHistory();
- const isNewAccessToRoute = checkNewAccessToRoute(routeHref, path);
- const allowedRoutes = getAllowedRoutes(routeHref, {
+ const isNewAccessToRoute = checkNewAccessToRoute(newRouteHref, path);
+ const allowedRoutes = getAllowedRoutes({
+ newRouteHref,
+ ...options,
isNewAccessToRoute,
- isStorageAllowed,
});
return {
diff --git a/src/theme/types/enums.ts b/src/theme/types/enums.ts
index aea2d519..b4e42533 100644
--- a/src/theme/types/enums.ts
+++ b/src/theme/types/enums.ts
@@ -6,4 +6,10 @@ export const enum ResctrictedAccessStatus {
export const enum PropSidebarItemType {
Category = 'category',
Link = 'link',
+ Html = 'html',
+}
+
+export const enum ResctrictedAccessStorageKeys {
+ Categories = 'categories',
+ Articles = 'articles',
}
diff --git a/src/theme/types/types.ts b/src/theme/types/types.ts
index ba33cd9e..8eba10ef 100644
--- a/src/theme/types/types.ts
+++ b/src/theme/types/types.ts
@@ -1,10 +1,21 @@
-import { ResctrictedAccessStatus } from './enums';
+import {
+ ResctrictedAccessStatus,
+ ResctrictedAccessStorageKeys,
+ PropSidebarItemType,
+} from './enums';
export type RestrictedHref = string | undefined;
export type ResctrictedAccessItem = Record;
export interface ResctrictedAccessItems {
- categories?: ResctrictedAccessItem;
- articles?: ResctrictedAccessItem;
+ [ResctrictedAccessStorageKeys.Categories]?: ResctrictedAccessItem;
+ [ResctrictedAccessStorageKeys.Articles]?: ResctrictedAccessItem;
+}
+
+export interface AllowedRoutesOptions {
+ isStorageAllowed: boolean;
+ type?: PropSidebarItemType;
+ newRouteHref?: string;
+ isNewAccessToRoute?: boolean;
}
diff --git a/src/theme/utils/filterSearchExcludeOptions.ts b/src/theme/utils/filterSearchExcludeOptions.ts
new file mode 100644
index 00000000..61d69f0f
--- /dev/null
+++ b/src/theme/utils/filterSearchExcludeOptions.ts
@@ -0,0 +1,23 @@
+import { getAllowedRoutes, flatRoutesResponse } from './routeAccessUtils';
+import restrictedAccessRoutes from '../../../config/restrictedAccessRoutes.json';
+
+const checkPartialExistanceInArray = (target: string, supportArray: string[]) =>
+ supportArray.some((item) => target.includes(item));
+
+const filterRestrictedRoutes = (restrictedRoutes: string[], itemsToExclude: string[]) =>
+ restrictedRoutes.filter(
+ (restrictedRoute) => !checkPartialExistanceInArray(restrictedRoute, itemsToExclude)
+ );
+
+export const filterSearchExcludeOptions = (searchDocs, isStorageAllowed: boolean) => {
+ const allowedRoutes = getAllowedRoutes({ isStorageAllowed });
+ const flatAllowedRoutes = flatRoutesResponse(allowedRoutes);
+ const filteredRestrictedRoutes = filterRestrictedRoutes(
+ restrictedAccessRoutes,
+ flatAllowedRoutes
+ );
+
+ return searchDocs.filter(
+ ({ url }) => !checkPartialExistanceInArray(url, filteredRestrictedRoutes)
+ );
+};
diff --git a/src/theme/utils/index.ts b/src/theme/utils/index.ts
index 8025d130..9cbf4c4c 100644
--- a/src/theme/utils/index.ts
+++ b/src/theme/utils/index.ts
@@ -1,8 +1,4 @@
export { getTermination } from './getTermination';
-export {
- checkHiddenSidebarItem,
- checkNewAccessToRoute,
- getAllowedRoutes,
- checkAllowedRoutes,
-} from './routeAccessUtils';
+export * from './routeAccessUtils';
+export { filterSearchExcludeOptions } from './filterSearchExcludeOptions';
export { ResctrictedAccessStorage } from './ResctrictedAccessStorage';
diff --git a/src/theme/utils/routeAccessUtils.ts b/src/theme/utils/routeAccessUtils.ts
index e5043a00..b68d4b01 100644
--- a/src/theme/utils/routeAccessUtils.ts
+++ b/src/theme/utils/routeAccessUtils.ts
@@ -1,10 +1,12 @@
import { PropSidebarItem } from '@docusaurus/plugin-content-docs';
import {
ResctrictedAccessItems,
- ResctrictedAccessItem,
ResctrictedAccessStatus,
PropSidebarItemType,
RestrictedHref,
+ ResctrictedAccessItem,
+ ResctrictedAccessStorageKeys,
+ AllowedRoutesOptions,
} from '../types';
import { ResctrictedAccessStorage } from './ResctrictedAccessStorage';
import { HIDDEN_CATEGORIES_LABELS } from '../constants';
@@ -12,38 +14,39 @@ import { HIDDEN_CATEGORIES_LABELS } from '../constants';
const getRoutesFromStorage = (): ResctrictedAccessItems =>
ResctrictedAccessStorage.getJSON() ?? {};
-interface AllowedRoutesOptions {
- isNewAccessToRoute: boolean;
- isStorageAllowed: boolean;
-}
-
-export const getAllowedRoutes = (
- routeHref: string,
- { isNewAccessToRoute, isStorageAllowed }: AllowedRoutesOptions
-) => {
+export const getAllowedRoutes = (options?: AllowedRoutesOptions) => {
+ const { isStorageAllowed, type, isNewAccessToRoute, newRouteHref } = options ?? {};
const previouslyAccessed: ResctrictedAccessItems = isStorageAllowed ? getRoutesFromStorage() : {};
if (!isNewAccessToRoute) {
return previouslyAccessed;
}
+ const storeKey =
+ type === PropSidebarItemType.Category
+ ? ResctrictedAccessStorageKeys.Categories
+ : ResctrictedAccessStorageKeys.Articles;
+
return {
...previouslyAccessed,
- categories: {
- ...(previouslyAccessed.categories ?? {}),
- [routeHref]: ResctrictedAccessStatus.Allowed,
+ [storeKey]: {
+ ...(previouslyAccessed[storeKey] ?? {}),
+ [newRouteHref]: ResctrictedAccessStatus.Allowed,
},
};
};
+export const flatRoutesResponse = (routesByTypes: ResctrictedAccessItems) =>
+ Object.values(routesByTypes).flatMap((routes) => Object.keys(routes));
+
export const checkAllowedRoutes = (allowedRoutes: ResctrictedAccessItems, routeHref: string) => {
if (!routeHref) {
return true;
}
return Object.values(allowedRoutes).reduce(
- (acc: boolean, type: ResctrictedAccessItem) =>
- acc || type[routeHref] === ResctrictedAccessStatus.Allowed,
+ (acc: boolean, routes: ResctrictedAccessItem) =>
+ acc || routes[routeHref] === ResctrictedAccessStatus.Allowed,
false
);
};