mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-02 02:42:41 +02:00
feat(v2): Algolia search theme (#1440)
* feat(v2): Algolia search plugin * patch PR #1440 (#1441) * alternative implementation * typo * refactor noop * rename SearchAlgolia -> SearchBar * changes.md
This commit is contained in:
parent
8aef4ec791
commit
384fd5708f
14 changed files with 116 additions and 44 deletions
|
@ -11,6 +11,9 @@ module.exports = function preset(context, opts = {}) {
|
||||||
{
|
{
|
||||||
name: '@docusaurus/theme-classic',
|
name: '@docusaurus/theme-classic',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '@docusaurus/theme-search-algolia',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ const path = require('path');
|
||||||
|
|
||||||
const DEFAULT_OPTIONS = {};
|
const DEFAULT_OPTIONS = {};
|
||||||
|
|
||||||
class DocusaurusThemeDefault {
|
class DocusaurusThemeClassic {
|
||||||
constructor(context, opts) {
|
constructor(context, opts) {
|
||||||
this.options = {...DEFAULT_OPTIONS, ...opts};
|
this.options = {...DEFAULT_OPTIONS, ...opts};
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -24,4 +24,4 @@ class DocusaurusThemeDefault {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DocusaurusThemeDefault;
|
module.exports = DocusaurusThemeClassic;
|
||||||
|
|
|
@ -10,9 +10,9 @@ import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
|
||||||
import Search from '@theme/Search';
|
import SearchBar from '@theme/SearchBar';
|
||||||
|
|
||||||
function Navbar(props) {
|
function Navbar() {
|
||||||
const context = useDocusaurusContext();
|
const context = useDocusaurusContext();
|
||||||
const {siteConfig = {}} = context;
|
const {siteConfig = {}} = context;
|
||||||
// TODO: navbar headerlinks should depends on theme, not siteConfig;
|
// TODO: navbar headerlinks should depends on theme, not siteConfig;
|
||||||
|
@ -20,7 +20,7 @@ function Navbar(props) {
|
||||||
baseUrl,
|
baseUrl,
|
||||||
headerLinks,
|
headerLinks,
|
||||||
headerIcon,
|
headerIcon,
|
||||||
algolia,
|
themeConfig: {algolia},
|
||||||
title,
|
title,
|
||||||
disableHeaderTitle,
|
disableHeaderTitle,
|
||||||
} = siteConfig;
|
} = siteConfig;
|
||||||
|
@ -41,8 +41,9 @@ function Navbar(props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link.href) {
|
if (link.href) {
|
||||||
// set link to specified href
|
// Set link to specified href.
|
||||||
return (
|
return (
|
||||||
<div key={link.label} className="navbar__item">
|
<div key={link.label} className="navbar__item">
|
||||||
<Link to={link.href} className="navbar__link">
|
<Link to={link.href} className="navbar__link">
|
||||||
|
@ -51,6 +52,7 @@ function Navbar(props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ function Navbar(props) {
|
||||||
<div className="navbar__items navbar__items--right">
|
<div className="navbar__items navbar__items--right">
|
||||||
{algolia && (
|
{algolia && (
|
||||||
<div className="navbar__search" key="search-box">
|
<div className="navbar__search" key="search-box">
|
||||||
<Search {...props} />
|
<SearchBar />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
8
packages/docusaurus-theme-classic/src/theme/SearchBar.js
Normal file
8
packages/docusaurus-theme-classic/src/theme/SearchBar.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {default} from '@docusaurus/Noop';
|
21
packages/docusaurus-theme-search-algolia/package.json
Normal file
21
packages/docusaurus-theme-search-algolia/package.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "@docusaurus/theme-search-algolia",
|
||||||
|
"version": "2.0.0-alpha.13",
|
||||||
|
"description": "Algolia search component for Docusaurus",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"docsearch.js": "^2.5.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@docusaurus/core": "^2.0.0",
|
||||||
|
"react": "^16.8.4",
|
||||||
|
"react-dom": "^16.8.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
}
|
27
packages/docusaurus-theme-search-algolia/src/index.js
Normal file
27
packages/docusaurus-theme-search-algolia/src/index.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const DEFAULT_OPTIONS = {};
|
||||||
|
|
||||||
|
class DocusaurusThemeSearchAlgolia {
|
||||||
|
constructor(context, opts) {
|
||||||
|
this.options = {...DEFAULT_OPTIONS, ...opts};
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return 'docusaurus-theme-search-algolia';
|
||||||
|
}
|
||||||
|
|
||||||
|
getThemePath() {
|
||||||
|
return path.resolve(__dirname, './theme');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DocusaurusThemeSearchAlgolia;
|
|
@ -22,7 +22,9 @@ class Search extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {siteConfig = {}, metadata = {}} = this.context;
|
const {siteConfig = {}, metadata = {}} = this.context;
|
||||||
const {version: thisVersion, language: thisLanguage} = metadata;
|
const {version: thisVersion, language: thisLanguage} = metadata;
|
||||||
const {algolia} = siteConfig;
|
const {
|
||||||
|
themeConfig: {algolia},
|
||||||
|
} = siteConfig;
|
||||||
|
|
||||||
// https://github.com/algolia/docsearch/issues/352
|
// https://github.com/algolia/docsearch/issues/352
|
||||||
const isClient = typeof window !== 'undefined';
|
const isClient = typeof window !== 'undefined';
|
|
@ -15,10 +15,6 @@ headerLinks: [
|
||||||
{ url: "help", label: "Help" },
|
{ url: "help", label: "Help" },
|
||||||
// Links to href destination/ external page
|
// Links to href destination/ external page
|
||||||
{ href: "https://github.com/", label: "GitHub" },
|
{ href: "https://github.com/", label: "GitHub" },
|
||||||
// Determines search bar position among links
|
|
||||||
{ search: true },
|
|
||||||
// Determines language drop down position among links
|
|
||||||
{ languages: true }
|
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
8
packages/docusaurus/lib/client/exports/Noop.js
Normal file
8
packages/docusaurus/lib/client/exports/Noop.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default () => null;
|
|
@ -55,35 +55,39 @@ module.exports = async function load(siteDir, cliOptions = {}) {
|
||||||
// These can be overriden in plugins/ through component swizzling.
|
// These can be overriden in plugins/ through component swizzling.
|
||||||
// However, we alias it here first as a fallback.
|
// However, we alias it here first as a fallback.
|
||||||
const themeFallback = path.resolve(__dirname, '../client/theme-fallback');
|
const themeFallback = path.resolve(__dirname, '../client/theme-fallback');
|
||||||
let themeAliases = await loadTheme(themeFallback);
|
const fallbackAliases = await loadTheme(themeFallback);
|
||||||
|
|
||||||
// create theme alias from plugins
|
// Create theme alias from plugins.
|
||||||
await Promise.all(
|
const pluginThemeAliases = await Promise.all(
|
||||||
plugins.map(async plugin => {
|
plugins.map(async plugin => {
|
||||||
if (!plugin.getThemePath) {
|
if (!plugin.getThemePath) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
const aliases = await loadTheme(plugin.getThemePath());
|
return loadTheme(plugin.getThemePath());
|
||||||
themeAliases = {
|
|
||||||
...themeAliases,
|
|
||||||
...aliases,
|
|
||||||
};
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// user's own theme alias override. Highest priority
|
// User's own theme alias override. Highest priority.
|
||||||
const themePath = path.resolve(siteDir, 'theme');
|
const themePath = path.resolve(siteDir, 'theme');
|
||||||
const aliases = await loadTheme(themePath);
|
const userAliases = await loadTheme(themePath);
|
||||||
themeAliases = {
|
|
||||||
...themeAliases,
|
|
||||||
...aliases,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make a fake plugin to resolve alias theme.
|
const combinedAliases = [
|
||||||
|
fallbackAliases,
|
||||||
|
...pluginThemeAliases,
|
||||||
|
userAliases,
|
||||||
|
].reduce(
|
||||||
|
(acc, curr) => ({
|
||||||
|
...acc,
|
||||||
|
...curr,
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make a fake plugin to resolve aliased theme components.
|
||||||
plugins.push({
|
plugins.push({
|
||||||
configureWebpack: () => ({
|
configureWebpack: () => ({
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: themeAliases,
|
alias: combinedAliases,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,6 @@ const REQUIRED_FIELDS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const OPTIONAL_FIELDS = [
|
const OPTIONAL_FIELDS = [
|
||||||
'algolia',
|
|
||||||
'customFields',
|
'customFields',
|
||||||
'defaultLanguage',
|
'defaultLanguage',
|
||||||
'disableHeaderTitle',
|
'disableHeaderTitle',
|
||||||
|
@ -32,6 +31,7 @@ const OPTIONAL_FIELDS = [
|
||||||
'markdownPlugins',
|
'markdownPlugins',
|
||||||
'plugins',
|
'plugins',
|
||||||
'presets',
|
'presets',
|
||||||
|
'themeConfig',
|
||||||
];
|
];
|
||||||
|
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
|
|
|
@ -20,16 +20,15 @@ module.exports = async function loadTheme(themePath) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const alias = {};
|
const alias = {};
|
||||||
await Promise.all(
|
|
||||||
themeComponentFiles.map(async relativeSource => {
|
themeComponentFiles.forEach(relativeSource => {
|
||||||
const filePath = path.join(themePath, relativeSource);
|
const filePath = path.join(themePath, relativeSource);
|
||||||
const fileName = fileToPath(relativeSource);
|
const fileName = fileToPath(relativeSource);
|
||||||
const aliasName = posixPath(
|
const aliasName = posixPath(
|
||||||
normalizeUrl(['@theme', fileName]).replace(/\/$/, ''),
|
normalizeUrl(['@theme', fileName]).replace(/\/$/, ''),
|
||||||
);
|
);
|
||||||
alias[aliasName] = filePath;
|
alias[aliasName] = filePath;
|
||||||
}),
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return alias;
|
return alias;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,10 +19,12 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
algolia: {
|
themeConfig: {
|
||||||
apiKey: '47ecd3b21be71c5822571b9f59e52544',
|
algolia: {
|
||||||
indexName: 'docusaurus-2',
|
apiKey: '47ecd3b21be71c5822571b9f59e52544',
|
||||||
algoliaOptions: {},
|
indexName: 'docusaurus-2',
|
||||||
|
algoliaOptions: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue