@docusaurus/theme-search-algolia 2.0.0-beta.ff31de0ff → 2.0.1

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.
Files changed (37) hide show
  1. package/lib/client/index.d.ts +7 -0
  2. package/lib/client/index.js +7 -0
  3. package/lib/client/useAlgoliaContextualFacetFilters.d.ts +7 -0
  4. package/lib/client/useAlgoliaContextualFacetFilters.js +15 -0
  5. package/lib/index.d.ts +9 -0
  6. package/lib/index.js +90 -0
  7. package/lib/templates/opensearch.d.ts +8 -0
  8. package/lib/templates/opensearch.js +23 -0
  9. package/lib/theme/SearchBar/index.d.ts +8 -0
  10. package/{src → lib}/theme/SearchBar/index.js +51 -60
  11. package/lib/theme/SearchBar/styles.css +21 -0
  12. package/lib/theme/SearchPage/index.d.ts +8 -0
  13. package/{src → lib}/theme/SearchPage/index.js +100 -131
  14. package/lib/theme/SearchPage/styles.module.css +119 -0
  15. package/lib/theme/SearchTranslations/index.d.ts +11 -0
  16. package/lib/theme/SearchTranslations/index.js +167 -0
  17. package/lib/validateThemeConfig.d.ts +15 -0
  18. package/lib/validateThemeConfig.js +44 -0
  19. package/package.json +43 -14
  20. package/src/client/index.ts +8 -0
  21. package/src/{theme/hooks/useAlgoliaContextualFacetFilters.js → client/useAlgoliaContextualFacetFilters.ts} +3 -3
  22. package/src/deps.d.ts +20 -0
  23. package/src/index.ts +116 -0
  24. package/src/templates/{opensearch.js → opensearch.ts} +7 -5
  25. package/src/theme/SearchBar/index.tsx +271 -0
  26. package/src/theme/SearchBar/styles.css +1 -0
  27. package/src/theme/SearchPage/index.tsx +535 -0
  28. package/src/theme/SearchPage/styles.module.css +15 -34
  29. package/src/theme/SearchTranslations/index.ts +172 -0
  30. package/src/theme-search-algolia.d.ts +42 -0
  31. package/src/types.d.ts +10 -0
  32. package/src/validateThemeConfig.ts +53 -0
  33. package/src/__tests__/validateThemeConfig.test.js +0 -121
  34. package/src/index.js +0 -92
  35. package/src/theme/SearchMetadatas/index.js +0 -25
  36. package/src/theme/hooks/useSearchQuery.js +0 -44
  37. package/src/validateThemeConfig.js +0 -45
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import {translate} from '@docusaurus/Translate';
8
+ const translations = {
9
+ button: {
10
+ buttonText: translate({
11
+ id: 'theme.SearchBar.label',
12
+ message: 'Search',
13
+ description: 'The ARIA label and placeholder for search button',
14
+ }),
15
+ buttonAriaLabel: translate({
16
+ id: 'theme.SearchBar.label',
17
+ message: 'Search',
18
+ description: 'The ARIA label and placeholder for search button',
19
+ }),
20
+ },
21
+ modal: {
22
+ searchBox: {
23
+ resetButtonTitle: translate({
24
+ id: 'theme.SearchModal.searchBox.resetButtonTitle',
25
+ message: 'Clear the query',
26
+ description: 'The label and ARIA label for search box reset button',
27
+ }),
28
+ resetButtonAriaLabel: translate({
29
+ id: 'theme.SearchModal.searchBox.resetButtonTitle',
30
+ message: 'Clear the query',
31
+ description: 'The label and ARIA label for search box reset button',
32
+ }),
33
+ cancelButtonText: translate({
34
+ id: 'theme.SearchModal.searchBox.cancelButtonText',
35
+ message: 'Cancel',
36
+ description: 'The label and ARIA label for search box cancel button',
37
+ }),
38
+ cancelButtonAriaLabel: translate({
39
+ id: 'theme.SearchModal.searchBox.cancelButtonText',
40
+ message: 'Cancel',
41
+ description: 'The label and ARIA label for search box cancel button',
42
+ }),
43
+ },
44
+ startScreen: {
45
+ recentSearchesTitle: translate({
46
+ id: 'theme.SearchModal.startScreen.recentSearchesTitle',
47
+ message: 'Recent',
48
+ description: 'The title for recent searches',
49
+ }),
50
+ noRecentSearchesText: translate({
51
+ id: 'theme.SearchModal.startScreen.noRecentSearchesText',
52
+ message: 'No recent searches',
53
+ description: 'The text when no recent searches',
54
+ }),
55
+ saveRecentSearchButtonTitle: translate({
56
+ id: 'theme.SearchModal.startScreen.saveRecentSearchButtonTitle',
57
+ message: 'Save this search',
58
+ description: 'The label for save recent search button',
59
+ }),
60
+ removeRecentSearchButtonTitle: translate({
61
+ id: 'theme.SearchModal.startScreen.removeRecentSearchButtonTitle',
62
+ message: 'Remove this search from history',
63
+ description: 'The label for remove recent search button',
64
+ }),
65
+ favoriteSearchesTitle: translate({
66
+ id: 'theme.SearchModal.startScreen.favoriteSearchesTitle',
67
+ message: 'Favorite',
68
+ description: 'The title for favorite searches',
69
+ }),
70
+ removeFavoriteSearchButtonTitle: translate({
71
+ id: 'theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle',
72
+ message: 'Remove this search from favorites',
73
+ description: 'The label for remove favorite search button',
74
+ }),
75
+ },
76
+ errorScreen: {
77
+ titleText: translate({
78
+ id: 'theme.SearchModal.errorScreen.titleText',
79
+ message: 'Unable to fetch results',
80
+ description: 'The title for error screen of search modal',
81
+ }),
82
+ helpText: translate({
83
+ id: 'theme.SearchModal.errorScreen.helpText',
84
+ message: 'You might want to check your network connection.',
85
+ description: 'The help text for error screen of search modal',
86
+ }),
87
+ },
88
+ footer: {
89
+ selectText: translate({
90
+ id: 'theme.SearchModal.footer.selectText',
91
+ message: 'to select',
92
+ description: 'The explanatory text of the action for the enter key',
93
+ }),
94
+ selectKeyAriaLabel: translate({
95
+ id: 'theme.SearchModal.footer.selectKeyAriaLabel',
96
+ message: 'Enter key',
97
+ description:
98
+ 'The ARIA label for the Enter key button that makes the selection',
99
+ }),
100
+ navigateText: translate({
101
+ id: 'theme.SearchModal.footer.navigateText',
102
+ message: 'to navigate',
103
+ description:
104
+ 'The explanatory text of the action for the Arrow up and Arrow down key',
105
+ }),
106
+ navigateUpKeyAriaLabel: translate({
107
+ id: 'theme.SearchModal.footer.navigateUpKeyAriaLabel',
108
+ message: 'Arrow up',
109
+ description:
110
+ 'The ARIA label for the Arrow up key button that makes the navigation',
111
+ }),
112
+ navigateDownKeyAriaLabel: translate({
113
+ id: 'theme.SearchModal.footer.navigateDownKeyAriaLabel',
114
+ message: 'Arrow down',
115
+ description:
116
+ 'The ARIA label for the Arrow down key button that makes the navigation',
117
+ }),
118
+ closeText: translate({
119
+ id: 'theme.SearchModal.footer.closeText',
120
+ message: 'to close',
121
+ description: 'The explanatory text of the action for Escape key',
122
+ }),
123
+ closeKeyAriaLabel: translate({
124
+ id: 'theme.SearchModal.footer.closeKeyAriaLabel',
125
+ message: 'Escape key',
126
+ description:
127
+ 'The ARIA label for the Escape key button that close the modal',
128
+ }),
129
+ searchByText: translate({
130
+ id: 'theme.SearchModal.footer.searchByText',
131
+ message: 'Search by',
132
+ description: 'The text explain that the search is making by Algolia',
133
+ }),
134
+ },
135
+ noResultsScreen: {
136
+ noResultsText: translate({
137
+ id: 'theme.SearchModal.noResultsScreen.noResultsText',
138
+ message: 'No results for',
139
+ description:
140
+ 'The text explains that there are no results for the following search',
141
+ }),
142
+ suggestedQueryText: translate({
143
+ id: 'theme.SearchModal.noResultsScreen.suggestedQueryText',
144
+ message: 'Try searching for',
145
+ description:
146
+ 'The text for the suggested query when no results are found for the following search',
147
+ }),
148
+ reportMissingResultsText: translate({
149
+ id: 'theme.SearchModal.noResultsScreen.reportMissingResultsText',
150
+ message: 'Believe this query should return results?',
151
+ description:
152
+ 'The text for the question where the user thinks there are missing results',
153
+ }),
154
+ reportMissingResultsLinkText: translate({
155
+ id: 'theme.SearchModal.noResultsScreen.reportMissingResultsLinkText',
156
+ message: 'Let us know.',
157
+ description: 'The text for the link to report missing results',
158
+ }),
159
+ },
160
+ },
161
+ placeholder: translate({
162
+ id: 'theme.SearchModal.placeholder',
163
+ message: 'Search docs',
164
+ description: 'The placeholder of the input of the DocSearch pop-up modal',
165
+ }),
166
+ };
167
+ export default translations;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { Joi } from '@docusaurus/utils-validation';
8
+ import type { ThemeConfig, ThemeConfigValidationContext } from '@docusaurus/types';
9
+ export declare const DEFAULT_CONFIG: {
10
+ contextualSearch: boolean;
11
+ searchParameters: {};
12
+ searchPagePath: string;
13
+ };
14
+ export declare const Schema: Joi.ObjectSchema<ThemeConfig>;
15
+ export declare function validateThemeConfig({ validate, themeConfig, }: ThemeConfigValidationContext<ThemeConfig>): ThemeConfig;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Facebook, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.validateThemeConfig = exports.Schema = exports.DEFAULT_CONFIG = void 0;
10
+ const utils_validation_1 = require("@docusaurus/utils-validation");
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',
17
+ };
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(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
40
+ });
41
+ function validateThemeConfig({ validate, themeConfig, }) {
42
+ return validate(exports.Schema, themeConfig);
43
+ }
44
+ exports.validateThemeConfig = validateThemeConfig;
package/package.json CHANGED
@@ -1,8 +1,22 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-search-algolia",
3
- "version": "2.0.0-beta.ff31de0ff",
3
+ "version": "2.0.1",
4
4
  "description": "Algolia search component for Docusaurus.",
5
- "main": "src/index.js",
5
+ "main": "lib/index.js",
6
+ "sideEffects": [
7
+ "*.css"
8
+ ],
9
+ "exports": {
10
+ "./client": {
11
+ "types": "./lib/client/index.d.ts",
12
+ "default": "./lib/client/index.js"
13
+ },
14
+ ".": {
15
+ "types": "./src/theme-search-algolia.d.ts",
16
+ "default": "./lib/index.js"
17
+ }
18
+ },
19
+ "types": "src/theme-search-algolia.d.ts",
6
20
  "publishConfig": {
7
21
  "access": "public"
8
22
  },
@@ -12,24 +26,39 @@
12
26
  "directory": "packages/docusaurus-theme-search-algolia"
13
27
  },
14
28
  "license": "MIT",
29
+ "scripts": {
30
+ "build": "tsc --build && node ../../admin/scripts/copyUntypedFiles.js && prettier --config ../../.prettierrc --write \"lib/theme/**/*.js\"",
31
+ "watch": "run-p -c copy:watch build:watch",
32
+ "build:watch": "tsc --build --watch",
33
+ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
34
+ },
15
35
  "dependencies": {
16
- "@docsearch/react": "^3.0.0-alpha.33",
17
- "@docusaurus/core": "2.0.0-beta.ff31de0ff",
18
- "@docusaurus/theme-common": "2.0.0-beta.ff31de0ff",
19
- "@docusaurus/utils": "2.0.0-beta.ff31de0ff",
20
- "@docusaurus/utils-validation": "2.0.0-beta.ff31de0ff",
21
- "algoliasearch": "^4.8.4",
22
- "algoliasearch-helper": "^3.3.4",
23
- "clsx": "^1.1.1",
24
- "eta": "^1.12.1",
25
- "lodash": "^4.17.20"
36
+ "@docsearch/react": "^3.1.1",
37
+ "@docusaurus/core": "2.0.1",
38
+ "@docusaurus/logger": "2.0.1",
39
+ "@docusaurus/plugin-content-docs": "2.0.1",
40
+ "@docusaurus/theme-common": "2.0.1",
41
+ "@docusaurus/theme-translations": "2.0.1",
42
+ "@docusaurus/utils": "2.0.1",
43
+ "@docusaurus/utils-validation": "2.0.1",
44
+ "algoliasearch": "^4.13.1",
45
+ "algoliasearch-helper": "^3.10.0",
46
+ "clsx": "^1.2.1",
47
+ "eta": "^1.12.3",
48
+ "fs-extra": "^10.1.0",
49
+ "lodash": "^4.17.21",
50
+ "tslib": "^2.4.0",
51
+ "utility-types": "^3.10.0"
52
+ },
53
+ "devDependencies": {
54
+ "@docusaurus/module-type-aliases": "2.0.1"
26
55
  },
27
56
  "peerDependencies": {
28
57
  "react": "^16.8.4 || ^17.0.0",
29
58
  "react-dom": "^16.8.4 || ^17.0.0"
30
59
  },
31
60
  "engines": {
32
- "node": ">=12.13.0"
61
+ "node": ">=16.14"
33
62
  },
34
- "gitHead": "6cacb313da4a21283fe08176097df89df836ee23"
63
+ "gitHead": "1ddee1c29cabf9bb52e4d78af6ebfaaabb1bc1f9"
35
64
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters';
@@ -5,13 +5,13 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import useContextualSearchFilters from '@theme/hooks/useContextualSearchFilters';
8
+ import {useContextualSearchFilters} from '@docusaurus/theme-common';
9
9
 
10
10
  // Translate search-engine agnostic search filters to Algolia search filters
11
- export default function useAlgoliaContextualFacetFilters() {
11
+ export function useAlgoliaContextualFacetFilters(): [string, string[]] {
12
12
  const {locale, tags} = useContextualSearchFilters();
13
13
 
14
- // seems safe to convert locale->language, see AlgoliaSearchMetadatas comment
14
+ // Seems safe to convert locale->language, see AlgoliaSearchMetadata comment
15
15
  const languageFilter = `language:${locale}`;
16
16
 
17
17
  const tagsFilter = tags.map((tag) => `docusaurus_tag:${tag}`);
package/src/deps.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ declare module '@docsearch/react/modal';
9
+
10
+ declare module '@docsearch/react/style';
11
+
12
+ // TODO incompatible declaration file
13
+ declare module 'eta' {
14
+ export const defaultConfig: object;
15
+
16
+ export function compile(
17
+ template: string,
18
+ options?: object,
19
+ ): (data: object, config: object) => string;
20
+ }
package/src/index.ts ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import path from 'path';
9
+ import fs from 'fs-extra';
10
+ import _ from 'lodash';
11
+ import logger from '@docusaurus/logger';
12
+ import {defaultConfig, compile} from 'eta';
13
+ import {normalizeUrl} from '@docusaurus/utils';
14
+ import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
15
+ import openSearchTemplate from './templates/opensearch';
16
+
17
+ import type {LoadContext, Plugin} from '@docusaurus/types';
18
+ import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
19
+
20
+ const getCompiledOpenSearchTemplate = _.memoize(() =>
21
+ compile(openSearchTemplate.trim()),
22
+ );
23
+
24
+ function renderOpenSearchTemplate(data: {
25
+ title: string;
26
+ siteUrl: string;
27
+ searchUrl: string;
28
+ faviconUrl: string | null;
29
+ }) {
30
+ const compiled = getCompiledOpenSearchTemplate();
31
+ return compiled(data, defaultConfig);
32
+ }
33
+
34
+ const OPEN_SEARCH_FILENAME = 'opensearch.xml';
35
+
36
+ export default function themeSearchAlgolia(context: LoadContext): Plugin<void> {
37
+ const {
38
+ baseUrl,
39
+ siteConfig: {title, url, favicon, themeConfig},
40
+ i18n: {currentLocale},
41
+ } = context;
42
+ const {
43
+ algolia: {searchPagePath},
44
+ } = themeConfig as ThemeConfig;
45
+
46
+ return {
47
+ name: 'docusaurus-theme-search-algolia',
48
+
49
+ getThemePath() {
50
+ return '../lib/theme';
51
+ },
52
+ getTypeScriptThemePath() {
53
+ return '../src/theme';
54
+ },
55
+
56
+ getDefaultCodeTranslationMessages() {
57
+ return readDefaultCodeTranslationMessages({
58
+ locale: currentLocale,
59
+ name: 'theme-search-algolia',
60
+ });
61
+ },
62
+
63
+ contentLoaded({actions: {addRoute}}) {
64
+ if (searchPagePath) {
65
+ addRoute({
66
+ path: normalizeUrl([baseUrl, searchPagePath]),
67
+ component: '@theme/SearchPage',
68
+ exact: true,
69
+ });
70
+ }
71
+ },
72
+
73
+ async postBuild({outDir}) {
74
+ if (searchPagePath) {
75
+ const siteUrl = normalizeUrl([url, baseUrl]);
76
+
77
+ try {
78
+ await fs.writeFile(
79
+ path.join(outDir, OPEN_SEARCH_FILENAME),
80
+ renderOpenSearchTemplate({
81
+ title,
82
+ siteUrl,
83
+ searchUrl: normalizeUrl([siteUrl, searchPagePath]),
84
+ faviconUrl: favicon ? normalizeUrl([siteUrl, favicon]) : null,
85
+ }),
86
+ );
87
+ } catch (err) {
88
+ logger.error('Generating OpenSearch file failed.');
89
+ throw err;
90
+ }
91
+ }
92
+ },
93
+
94
+ injectHtmlTags() {
95
+ if (!searchPagePath) {
96
+ return {};
97
+ }
98
+
99
+ return {
100
+ headTags: [
101
+ {
102
+ tagName: 'link',
103
+ attributes: {
104
+ rel: 'search',
105
+ type: 'application/opensearchdescription+xml',
106
+ title,
107
+ href: normalizeUrl([baseUrl, OPEN_SEARCH_FILENAME]),
108
+ },
109
+ },
110
+ ],
111
+ };
112
+ },
113
+ };
114
+ }
115
+
116
+ export {validateThemeConfig} from './validateThemeConfig';
@@ -5,16 +5,18 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- module.exports = `
8
+ export default `
9
9
  <?xml version="1.0" encoding="UTF-8"?>
10
10
  <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
11
11
  xmlns:moz="http://www.mozilla.org/2006/browser/search/">
12
12
  <ShortName><%= it.title %></ShortName>
13
13
  <Description>Search <%= it.title %></Description>
14
14
  <InputEncoding>UTF-8</InputEncoding>
15
- <Image width="16" height="16" type="image/x-icon"><%= it.favicon %></Image>
16
- <Url type="text/html" method="get" template="<%= it.url %>search?q={searchTerms}"/>
17
- <Url type="application/opensearchdescription+xml" rel="self" template="<%= it.url %>opensearch.xml" />
18
- <moz:SearchForm><%= it.url %></moz:SearchForm>
15
+ <% if (it.faviconUrl) { _%>
16
+ <Image width="16" height="16" type="image/x-icon"><%= it.faviconUrl %></Image>
17
+ <% } _%>
18
+ <Url type="text/html" method="get" template="<%= it.searchUrl %>?q={searchTerms}"/>
19
+ <Url type="application/opensearchdescription+xml" rel="self" template="<%= it.siteUrl %>opensearch.xml" />
20
+ <moz:SearchForm><%= it.siteUrl %></moz:SearchForm>
19
21
  </OpenSearchDescription>
20
22
  `;