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:
Yangshun Tay 2019-05-08 01:21:11 -07:00 committed by Endi
parent 8aef4ec791
commit 384fd5708f
14 changed files with 116 additions and 44 deletions

View file

@ -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: [
{ {

View file

@ -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;

View file

@ -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>

View 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';

View 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"
}
}

View 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;

View file

@ -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';

View file

@ -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 }
], ],
``` ```

View 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;

View file

@ -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,
}, },
}), }),
}); });

View file

@ -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 = {

View file

@ -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;
}; };

View file

@ -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: [
[ [