@docusaurus/theme-search-algolia 2.0.0-beta.20 → 2.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,4 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters';
7
+ export { useAlgoliaContextualFacetFilters } from './useAlgoliaContextualFacetFilters';
@@ -4,12 +4,12 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import {useContextualSearchFilters} from '@docusaurus/theme-common';
7
+ import { useContextualSearchFilters } from '@docusaurus/theme-common';
8
8
  // Translate search-engine agnostic search filters to Algolia search filters
9
9
  export function useAlgoliaContextualFacetFilters() {
10
- const {locale, tags} = useContextualSearchFilters();
11
- // Seems safe to convert locale->language, see AlgoliaSearchMetadata comment
12
- const languageFilter = `language:${locale}`;
13
- const tagsFilter = tags.map((tag) => `docusaurus_tag:${tag}`);
14
- return [languageFilter, tagsFilter];
10
+ const { locale, tags } = useContextualSearchFilters();
11
+ // Seems safe to convert locale->language, see AlgoliaSearchMetadata comment
12
+ const languageFilter = `language:${locale}`;
13
+ const tagsFilter = tags.map((tag) => `docusaurus_tag:${tag}`);
14
+ return [languageFilter, tagsFilter];
15
15
  }
package/lib/index.js CHANGED
@@ -1,107 +1,90 @@
1
- 'use strict';
1
+ "use strict";
2
2
  /**
3
3
  * Copyright (c) Facebook, Inc. and its affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- Object.defineProperty(exports, '__esModule', {value: true});
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.validateThemeConfig = void 0;
10
- const tslib_1 = require('tslib');
11
- const path_1 = tslib_1.__importDefault(require('path'));
12
- const fs_extra_1 = tslib_1.__importDefault(require('fs-extra'));
13
- const eta_1 = require('eta');
14
- const utils_1 = require('@docusaurus/utils');
15
- const theme_translations_1 = require('@docusaurus/theme-translations');
16
- const logger_1 = tslib_1.__importDefault(require('@docusaurus/logger'));
17
- const opensearch_1 = tslib_1.__importDefault(require('./templates/opensearch'));
18
- const lodash_1 = tslib_1.__importDefault(require('lodash'));
19
- const getCompiledOpenSearchTemplate = lodash_1.default.memoize(() =>
20
- (0, eta_1.compile)(opensearch_1.default.trim()),
21
- );
10
+ const tslib_1 = require("tslib");
11
+ const path_1 = tslib_1.__importDefault(require("path"));
12
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
13
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
14
+ const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
15
+ const eta_1 = require("eta");
16
+ const utils_1 = require("@docusaurus/utils");
17
+ const theme_translations_1 = require("@docusaurus/theme-translations");
18
+ const opensearch_1 = tslib_1.__importDefault(require("./templates/opensearch"));
19
+ const getCompiledOpenSearchTemplate = lodash_1.default.memoize(() => (0, eta_1.compile)(opensearch_1.default.trim()));
22
20
  function renderOpenSearchTemplate(data) {
23
- const compiled = getCompiledOpenSearchTemplate();
24
- return compiled(data, eta_1.defaultConfig);
21
+ const compiled = getCompiledOpenSearchTemplate();
22
+ return compiled(data, eta_1.defaultConfig);
25
23
  }
26
24
  const OPEN_SEARCH_FILENAME = 'opensearch.xml';
27
25
  function themeSearchAlgolia(context) {
28
- const {
29
- baseUrl,
30
- siteConfig: {title, url, favicon, themeConfig},
31
- i18n: {currentLocale},
32
- } = context;
33
- const {
34
- algolia: {searchPagePath},
35
- } = themeConfig;
36
- return {
37
- name: 'docusaurus-theme-search-algolia',
38
- getThemePath() {
39
- return '../lib/theme';
40
- },
41
- getTypeScriptThemePath() {
42
- return '../src/theme';
43
- },
44
- getDefaultCodeTranslationMessages() {
45
- return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
46
- locale: currentLocale,
47
- name: 'theme-search-algolia',
48
- });
49
- },
50
- async contentLoaded({actions: {addRoute}}) {
51
- if (searchPagePath) {
52
- addRoute({
53
- path: (0, utils_1.normalizeUrl)([baseUrl, searchPagePath]),
54
- component: '@theme/SearchPage',
55
- exact: true,
56
- });
57
- }
58
- },
59
- async postBuild({outDir}) {
60
- if (searchPagePath) {
61
- const siteUrl = (0, utils_1.normalizeUrl)([url, baseUrl]);
62
- try {
63
- await fs_extra_1.default.writeFile(
64
- path_1.default.join(outDir, OPEN_SEARCH_FILENAME),
65
- renderOpenSearchTemplate({
66
- title,
67
- siteUrl,
68
- searchUrl: (0, utils_1.normalizeUrl)([siteUrl, searchPagePath]),
69
- faviconUrl: favicon
70
- ? (0, utils_1.normalizeUrl)([siteUrl, favicon])
71
- : null,
72
- }),
73
- );
74
- } catch (err) {
75
- logger_1.default.error('Generating OpenSearch file failed.');
76
- throw err;
77
- }
78
- }
79
- },
80
- injectHtmlTags() {
81
- if (!searchPagePath) {
82
- return {};
83
- }
84
- return {
85
- headTags: [
86
- {
87
- tagName: 'link',
88
- attributes: {
89
- rel: 'search',
90
- type: 'application/opensearchdescription+xml',
91
- title,
92
- href: (0, utils_1.normalizeUrl)([baseUrl, OPEN_SEARCH_FILENAME]),
93
- },
94
- },
95
- ],
96
- };
97
- },
98
- };
26
+ const { baseUrl, siteConfig: { title, url, favicon, themeConfig }, i18n: { currentLocale }, } = context;
27
+ const { algolia: { searchPagePath }, } = themeConfig;
28
+ return {
29
+ name: 'docusaurus-theme-search-algolia',
30
+ getThemePath() {
31
+ return '../lib/theme';
32
+ },
33
+ getTypeScriptThemePath() {
34
+ return '../src/theme';
35
+ },
36
+ getDefaultCodeTranslationMessages() {
37
+ return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
38
+ locale: currentLocale,
39
+ name: 'theme-search-algolia',
40
+ });
41
+ },
42
+ contentLoaded({ actions: { addRoute } }) {
43
+ if (searchPagePath) {
44
+ addRoute({
45
+ path: (0, utils_1.normalizeUrl)([baseUrl, searchPagePath]),
46
+ component: '@theme/SearchPage',
47
+ exact: true,
48
+ });
49
+ }
50
+ },
51
+ async postBuild({ outDir }) {
52
+ if (searchPagePath) {
53
+ const siteUrl = (0, utils_1.normalizeUrl)([url, baseUrl]);
54
+ try {
55
+ await fs_extra_1.default.writeFile(path_1.default.join(outDir, OPEN_SEARCH_FILENAME), renderOpenSearchTemplate({
56
+ title,
57
+ siteUrl,
58
+ searchUrl: (0, utils_1.normalizeUrl)([siteUrl, searchPagePath]),
59
+ faviconUrl: favicon ? (0, utils_1.normalizeUrl)([siteUrl, favicon]) : null,
60
+ }));
61
+ }
62
+ catch (err) {
63
+ logger_1.default.error('Generating OpenSearch file failed.');
64
+ throw err;
65
+ }
66
+ }
67
+ },
68
+ injectHtmlTags() {
69
+ if (!searchPagePath) {
70
+ return {};
71
+ }
72
+ return {
73
+ headTags: [
74
+ {
75
+ tagName: 'link',
76
+ attributes: {
77
+ rel: 'search',
78
+ type: 'application/opensearchdescription+xml',
79
+ title,
80
+ href: (0, utils_1.normalizeUrl)([baseUrl, OPEN_SEARCH_FILENAME]),
81
+ },
82
+ },
83
+ ],
84
+ };
85
+ },
86
+ };
99
87
  }
100
88
  exports.default = themeSearchAlgolia;
101
- var validateThemeConfig_1 = require('./validateThemeConfig');
102
- Object.defineProperty(exports, 'validateThemeConfig', {
103
- enumerable: true,
104
- get: function () {
105
- return validateThemeConfig_1.validateThemeConfig;
106
- },
107
- });
89
+ var validateThemeConfig_1 = require("./validateThemeConfig");
90
+ Object.defineProperty(exports, "validateThemeConfig", { enumerable: true, get: function () { return validateThemeConfig_1.validateThemeConfig; } });
@@ -1,11 +1,11 @@
1
- 'use strict';
1
+ "use strict";
2
2
  /**
3
3
  * Copyright (c) Facebook, Inc. and its affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- Object.defineProperty(exports, '__esModule', {value: true});
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.default = `
10
10
  <?xml version="1.0" encoding="UTF-8"?>
11
11
  <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
@@ -6,9 +6,9 @@
6
6
  */
7
7
  /* eslint-disable jsx-a11y/no-autofocus */
8
8
  import React, {useEffect, useState, useReducer, useRef} from 'react';
9
+ import clsx from 'clsx';
9
10
  import algoliaSearch from 'algoliasearch/lite';
10
11
  import algoliaSearchHelper from 'algoliasearch-helper';
11
- import clsx from 'clsx';
12
12
  import Head from '@docusaurus/Head';
13
13
  import Link from '@docusaurus/Link';
14
14
  import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
@@ -22,8 +22,8 @@ import {
22
22
  } from '@docusaurus/theme-common';
23
23
  import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
24
24
  import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
25
- import Layout from '@theme/Layout';
26
25
  import Translate, {translate} from '@docusaurus/Translate';
26
+ import Layout from '@theme/Layout';
27
27
  import styles from './styles.module.css';
28
28
  // Very simple pluralization: probably good enough for now
29
29
  function useDocumentsFoundPlural() {
@@ -11,5 +11,5 @@ export declare const DEFAULT_CONFIG: {
11
11
  searchParameters: {};
12
12
  searchPagePath: string;
13
13
  };
14
- export declare const Schema: Joi.ObjectSchema<any>;
14
+ export declare const Schema: Joi.ObjectSchema<ThemeConfig>;
15
15
  export declare function validateThemeConfig({ validate, themeConfig, }: ThemeConfigValidationContext<ThemeConfig>): ThemeConfig;
@@ -1,50 +1,44 @@
1
- 'use strict';
1
+ "use strict";
2
2
  /**
3
3
  * Copyright (c) Facebook, Inc. and its affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- Object.defineProperty(exports, '__esModule', {value: true});
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.validateThemeConfig = exports.Schema = exports.DEFAULT_CONFIG = void 0;
10
- const utils_validation_1 = require('@docusaurus/utils-validation');
10
+ const utils_validation_1 = require("@docusaurus/utils-validation");
11
11
  exports.DEFAULT_CONFIG = {
12
- // Enabled by default, as it makes sense in most cases
13
- // see also https://github.com/facebook/docusaurus/issues/5880
14
- contextualSearch: true,
15
- searchParameters: {},
16
- searchPagePath: 'search',
12
+ // Enabled by default, as it makes sense in most cases
13
+ // see also https://github.com/facebook/docusaurus/issues/5880
14
+ contextualSearch: true,
15
+ searchParameters: {},
16
+ searchPagePath: 'search',
17
17
  };
18
18
  exports.Schema = utils_validation_1.Joi.object({
19
- algolia: utils_validation_1.Joi.object({
20
- // Docusaurus attributes
21
- contextualSearch: utils_validation_1.Joi.boolean().default(
22
- exports.DEFAULT_CONFIG.contextualSearch,
23
- ),
24
- externalUrlRegex: utils_validation_1.Joi.string().optional(),
25
- // Algolia attributes
26
- appId: utils_validation_1.Joi.string().required().messages({
27
- 'any.required':
28
- '"algolia.appId" is required. If you haven\'t migrated to the new DocSearch infra, please refer to the blog post for instructions: https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration',
29
- }),
30
- apiKey: utils_validation_1.Joi.string().required(),
31
- indexName: utils_validation_1.Joi.string().required(),
32
- searchParameters: utils_validation_1.Joi.object()
33
- .default(exports.DEFAULT_CONFIG.searchParameters)
34
- .unknown(),
35
- searchPagePath: utils_validation_1.Joi.alternatives()
36
- .try(
37
- utils_validation_1.Joi.boolean().invalid(true),
38
- utils_validation_1.Joi.string(),
39
- )
40
- .allow(null)
41
- .default(exports.DEFAULT_CONFIG.searchPagePath),
42
- })
43
- .label('themeConfig.algolia')
44
- .required()
45
- .unknown(), // DocSearch 3 is still alpha: don't validate the rest for now
19
+ algolia: utils_validation_1.Joi.object({
20
+ // Docusaurus attributes
21
+ contextualSearch: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.contextualSearch),
22
+ externalUrlRegex: utils_validation_1.Joi.string().optional(),
23
+ // Algolia attributes
24
+ appId: utils_validation_1.Joi.string().required().messages({
25
+ 'any.required': '"algolia.appId" is required. If you haven\'t migrated to the new DocSearch infra, please refer to the blog post for instructions: https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration',
26
+ }),
27
+ apiKey: utils_validation_1.Joi.string().required(),
28
+ indexName: utils_validation_1.Joi.string().required(),
29
+ searchParameters: utils_validation_1.Joi.object()
30
+ .default(exports.DEFAULT_CONFIG.searchParameters)
31
+ .unknown(),
32
+ searchPagePath: utils_validation_1.Joi.alternatives()
33
+ .try(utils_validation_1.Joi.boolean().invalid(true), utils_validation_1.Joi.string())
34
+ .allow(null)
35
+ .default(exports.DEFAULT_CONFIG.searchPagePath),
36
+ })
37
+ .label('themeConfig.algolia')
38
+ .required()
39
+ .unknown(), // DocSearch 3 is still alpha: don't validate the rest for now
46
40
  });
47
- function validateThemeConfig({validate, themeConfig}) {
48
- return validate(exports.Schema, themeConfig);
41
+ function validateThemeConfig({ validate, themeConfig, }) {
42
+ return validate(exports.Schema, themeConfig);
49
43
  }
50
44
  exports.validateThemeConfig = validateThemeConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-search-algolia",
3
- "version": "2.0.0-beta.20",
3
+ "version": "2.0.0-beta.21",
4
4
  "description": "Algolia search component for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": [
@@ -21,22 +21,21 @@
21
21
  },
22
22
  "license": "MIT",
23
23
  "scripts": {
24
- "build": "yarn build:server && yarn build:client && yarn build:copy && yarn build:format",
25
- "build:server": "tsc --project tsconfig.server.json",
26
- "build:client": "tsc --project tsconfig.client.json",
27
- "build:copy": "node copyUntypedFiles.mjs",
28
- "build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
24
+ "build": "tsc --build && node ../../admin/scripts/copyUntypedFiles.js && prettier --config ../../.prettierrc --write \"lib/theme/**/*.js\"",
25
+ "watch": "run-p -c copy:watch build:watch",
26
+ "build:watch": "tsc --build --watch",
27
+ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
29
28
  },
30
29
  "dependencies": {
31
- "@docsearch/react": "^3.0.0",
32
- "@docusaurus/core": "2.0.0-beta.20",
33
- "@docusaurus/logger": "2.0.0-beta.20",
34
- "@docusaurus/plugin-content-docs": "2.0.0-beta.20",
35
- "@docusaurus/theme-common": "2.0.0-beta.20",
36
- "@docusaurus/theme-translations": "2.0.0-beta.20",
37
- "@docusaurus/utils": "2.0.0-beta.20",
38
- "@docusaurus/utils-validation": "2.0.0-beta.20",
39
- "algoliasearch": "^4.13.0",
30
+ "@docsearch/react": "^3.1.0",
31
+ "@docusaurus/core": "2.0.0-beta.21",
32
+ "@docusaurus/logger": "2.0.0-beta.21",
33
+ "@docusaurus/plugin-content-docs": "2.0.0-beta.21",
34
+ "@docusaurus/theme-common": "2.0.0-beta.21",
35
+ "@docusaurus/theme-translations": "2.0.0-beta.21",
36
+ "@docusaurus/utils": "2.0.0-beta.21",
37
+ "@docusaurus/utils-validation": "2.0.0-beta.21",
38
+ "algoliasearch": "^4.13.1",
40
39
  "algoliasearch-helper": "^3.8.2",
41
40
  "clsx": "^1.1.1",
42
41
  "eta": "^1.12.3",
@@ -46,14 +45,14 @@
46
45
  "utility-types": "^3.10.0"
47
46
  },
48
47
  "devDependencies": {
49
- "@docusaurus/module-type-aliases": "2.0.0-beta.20"
48
+ "@docusaurus/module-type-aliases": "2.0.0-beta.21"
50
49
  },
51
50
  "peerDependencies": {
52
51
  "react": "^16.8.4 || ^17.0.0",
53
52
  "react-dom": "^16.8.4 || ^17.0.0"
54
53
  },
55
54
  "engines": {
56
- "node": ">=14"
55
+ "node": ">=16.14"
57
56
  },
58
- "gitHead": "ed5cdba401a5948e187e927039b142a0decc702d"
57
+ "gitHead": "69ac49fc6909517f13615ee40290c4bd00c39df4"
59
58
  }
package/src/index.ts CHANGED
@@ -7,12 +7,12 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
+ import _ from 'lodash';
11
+ import logger from '@docusaurus/logger';
10
12
  import {defaultConfig, compile} from 'eta';
11
13
  import {normalizeUrl} from '@docusaurus/utils';
12
14
  import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
13
- import logger from '@docusaurus/logger';
14
15
  import openSearchTemplate from './templates/opensearch';
15
- import _ from 'lodash';
16
16
 
17
17
  import type {LoadContext, Plugin} from '@docusaurus/types';
18
18
  import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
@@ -60,7 +60,7 @@ export default function themeSearchAlgolia(context: LoadContext): Plugin<void> {
60
60
  });
61
61
  },
62
62
 
63
- async contentLoaded({actions: {addRoute}}) {
63
+ contentLoaded({actions: {addRoute}}) {
64
64
  if (searchPagePath) {
65
65
  addRoute({
66
66
  path: normalizeUrl([baseUrl, searchPagePath]),
@@ -14,7 +14,6 @@ import Link from '@docusaurus/Link';
14
14
  import Head from '@docusaurus/Head';
15
15
  import {isRegexpStringMatch, useSearchPage} from '@docusaurus/theme-common';
16
16
  import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react';
17
- import type {SearchClient} from 'algoliasearch/lite';
18
17
  import {useAlgoliaContextualFacetFilters} from '@docusaurus/theme-search-algolia/client';
19
18
  import Translate, {translate} from '@docusaurus/Translate';
20
19
 
@@ -26,6 +25,7 @@ import type {
26
25
  InternalDocSearchHit,
27
26
  StoredDocSearchHit,
28
27
  } from '@docsearch/react/dist/esm/types';
28
+ import type {SearchClient} from 'algoliasearch/lite';
29
29
  import type {AutocompleteState} from '@algolia/autocomplete-core';
30
30
 
31
31
  type DocSearchProps = Omit<
@@ -75,7 +75,7 @@ type FacetFilters = Required<
75
75
  function mergeFacetFilters(f1: FacetFilters, f2: FacetFilters): FacetFilters {
76
76
  const normalize = (
77
77
  f: FacetFilters,
78
- ): readonly string[] | ReadonlyArray<string | readonly string[]> =>
78
+ ): readonly string[] | readonly (string | readonly string[])[] =>
79
79
  typeof f === 'string' ? [f] : f;
80
80
  return [...normalize(f1), ...normalize(f2)] as FacetFilters;
81
81
  }
@@ -120,7 +120,9 @@ function DocSearch({
120
120
  }
121
121
 
122
122
  return Promise.all([
123
- import('@docsearch/react/modal'),
123
+ import('@docsearch/react/modal') as Promise<
124
+ typeof import('@docsearch/react')
125
+ >,
124
126
  import('@docsearch/react/style'),
125
127
  import('./styles.css'),
126
128
  ]).then(([{DocSearchModal: Modal}]) => {
@@ -8,10 +8,10 @@
8
8
  /* eslint-disable jsx-a11y/no-autofocus */
9
9
 
10
10
  import React, {useEffect, useState, useReducer, useRef} from 'react';
11
+ import clsx from 'clsx';
11
12
 
12
13
  import algoliaSearch from 'algoliasearch/lite';
13
14
  import algoliaSearchHelper from 'algoliasearch-helper';
14
- import clsx from 'clsx';
15
15
 
16
16
  import Head from '@docusaurus/Head';
17
17
  import Link from '@docusaurus/Link';
@@ -26,8 +26,9 @@ import {
26
26
  } from '@docusaurus/theme-common';
27
27
  import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
28
28
  import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
29
- import Layout from '@theme/Layout';
30
29
  import Translate, {translate} from '@docusaurus/Translate';
30
+ import Layout from '@theme/Layout';
31
+
31
32
  import styles from './styles.module.css';
32
33
  import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
33
34
 
@@ -236,10 +237,14 @@ function SearchPageContent(): JSX.Element {
236
237
  url,
237
238
  _highlightResult: {hierarchy},
238
239
  _snippetResult: snippet = {},
240
+ }: {
241
+ url: string;
242
+ _highlightResult: {hierarchy: {[key: string]: {value: string}}};
243
+ _snippetResult: {content?: {value: string}};
239
244
  }) => {
240
245
  const parsedURL = new URL(url);
241
246
  const titles = Object.keys(hierarchy).map((key) =>
242
- sanitizeValue(hierarchy[key].value),
247
+ sanitizeValue(hierarchy[key]!.value),
243
248
  );
244
249
 
245
250
  return {
@@ -20,7 +20,7 @@ export const DEFAULT_CONFIG = {
20
20
  searchPagePath: 'search',
21
21
  };
22
22
 
23
- export const Schema = Joi.object({
23
+ export const Schema = Joi.object<ThemeConfig>({
24
24
  algolia: Joi.object({
25
25
  // Docusaurus attributes
26
26
  contextualSearch: Joi.boolean().default(DEFAULT_CONFIG.contextualSearch),