feat(v2): headerlinks (#1074)

* feat(v2): headerlinks

* fix test

* nits

* remove tictactoe:

* headerIcon

* nits

* remove lang dropdown

* fix failing test

* search box

* algolia search

* use babel-eslint to resolve dynamic import

* nits

* favicon and title

* Update .eslintignore
This commit is contained in:
Endilie Yacop Sucipto 2018-10-28 16:32:19 +08:00 committed by GitHub
parent d4458b394c
commit 85336649d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 1205 additions and 2292 deletions

View file

@ -21,12 +21,16 @@ export default class BlogPage extends React.Component {
blogMetadatas,
language,
children,
siteConfig,
siteConfig = {},
} = this.props;
const {posts} = metadata;
const {baseUrl, favicon} = siteConfig;
return (
<Layout {...this.props}>
<Helmet defaultTitle={siteConfig.title}>
<Helmet>
<title>{'Blog'}</title>
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{language && <html lang={language} />}
{language && <meta name="docsearch:language" content={language} />}
</Helmet>

View file

@ -80,11 +80,14 @@ export default class BlogPost extends React.Component {
}
render() {
const {metadata, children, siteConfig} = this.props;
const {language} = metadata;
const {metadata, children, siteConfig = {}} = this.props;
const {baseUrl, favicon} = siteConfig;
const {language, title} = metadata;
return (
<Layout {...this.props}>
<Helmet defaultTitle={siteConfig.title}>
{title && <title>{title}</title>}
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{language && <html lang={language} />}
</Helmet>
{this.renderPostHeader()}

View file

@ -22,22 +22,30 @@ class Doc extends React.Component {
const {
docsMetadatas,
docsSidebars,
env,
location,
metadata,
pagesMetadatas,
siteConfig,
siteConfig = {},
route,
} = this.props;
const {language, version} = metadata;
const {baseUrl, favicon} = siteConfig;
return (
<div>
<Helmet>
<title>{(metadata && metadata.title) || siteConfig.title}</title>
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{language && <html lang={language} />}
{language && <meta name="docsearch:language" content={language} />}
{version && <meta name="docsearch:version" content={version} />}
</Helmet>
<Navbar docsMetadatas={docsMetadatas} />
<Navbar
docsMetadatas={docsMetadatas}
env={env}
metadata={metadata}
siteConfig={siteConfig}
/>
<Sidebar
docsMetadatas={docsMetadatas}
docsSidebars={docsSidebars}

View file

@ -19,11 +19,19 @@ export default class Layout extends React.Component {
children,
pagesMetadatas = [],
docsMetadatas = {},
env,
siteConfig,
location,
metadata,
} = this.props;
return (
<div>
<Navbar docsMetadatas={docsMetadatas} />
<Navbar
docsMetadatas={docsMetadatas}
env={env}
metadata={metadata}
siteConfig={siteConfig}
/>
{children}
<Footer
docsMetadatas={docsMetadatas}

View file

@ -1,64 +1,112 @@
/**
* 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.
*/
import React from 'react';
import {NavLink} from 'react-router-dom';
import Search from '@theme/Search';
import styles from './styles.module.css';
function Navbar() {
function Navbar(props) {
const {siteConfig = {}, env = {}, metadata = {}, docsMetadatas = {}} = props;
const {baseUrl, headerLinks, headerIcon, algolia} = siteConfig;
const {language: thisLanguage, version: thisVersion} = metadata;
const translationEnabled = env.translation.enabled;
const versioningEnabled = env.versioning.enabled;
// function to generate each header link
const makeLinks = link => {
if (link.search && algolia) {
// return algolia search bar
return (
<li className={styles.navListItem} key="search-box">
<Search {...props} />
</li>
);
}
if (link.languages) {
// TODO in the future for <LanguageDropdown /> like in v1
return null;
}
if (link.doc) {
// set link to document with current page's language/version
const langPart = translationEnabled ? `${thisLanguage}-` : '';
const versionPart =
versioningEnabled && thisVersion !== 'next'
? `version-${thisVersion || env.versioning.defaultVersion}-`
: '';
const id = langPart + versionPart + link.doc;
if (!docsMetadatas[id]) {
const errorStr = `We could not find the doc wih id: ${id}. Please check your headerLinks correctly\n`;
throw new Error(errorStr);
}
return (
<li key={link.doc} className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to={docsMetadatas[id].permalink}>
{link.label}
</NavLink>
</li>
);
}
if (link.page) {
// set link to page with current page's language if appropriate
const pageHref = `${baseUrl}${thisLanguage ? `${thisLanguage}/` : ''}${
link.page
}`;
return (
<li key={link.page} className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to={pageHref}>
{link.label}
</NavLink>
</li>
);
}
if (link.href) {
// set link to specified href
return (
<li key={link.label} className={styles.navListItem}>
<a href={link.href} className={styles.navLink}>
{link.label}
</a>
</li>
);
}
if (link.blog) {
// set link to blog url
const blogUrl = `${baseUrl}blog`;
return (
<li key="Blog" className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to={blogUrl}>
Blog
</NavLink>
</li>
);
}
return null;
};
return (
<nav className={styles.navbar}>
<div className={styles.navbarInner}>
<ul className={styles.navList}>
<li className={styles.navListItem}>
<li key="logo" className={styles.navListItem}>
<NavLink className={styles.navBrand} to="/">
<img
alt="Docusaurus Logo"
className={styles.navLogo}
src="/img/docusaurus-logo.svg"
src={baseUrl + headerIcon}
/>
<strong>Docusaurus</strong>
</NavLink>
</li>
<li className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to="/docs/installation">
Docs
</NavLink>
</li>
<li className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to="/blog">
Blog
</NavLink>
</li>
<li className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to="https://github.com/facebook/docusaurus">
GitHub
</NavLink>
</li>
{/* Object.values(props.docsMetadatas).map(metadata => (
<li key={metadata.permalink} className={styles.navListItem}>
<NavLink
activeClassName={styles.navLinkActive}
className={styles.navLink}
to={metadata.permalink}>
{metadata.title}
</NavLink>
</li>
)) */}
{headerLinks.map(makeLinks)}
</ul>
</div>
</nav>

View file

@ -11,7 +11,7 @@ import Layout from '@theme/Layout';
export default class NotFound extends React.Component {
render() {
return (
<Layout>
<Layout {...this.props}>
<div>404 Page Not Found</div>
<div>
<img

View file

@ -13,11 +13,13 @@ import Layout from '@theme/Layout'; // eslint-disable-line
export default class Pages extends React.Component {
render() {
const {metadata, children, siteConfig} = this.props;
const {metadata, children, siteConfig = {}} = this.props;
const {baseUrl, favicon} = siteConfig;
const {language} = metadata;
return (
<Layout {...this.props}>
<Helmet defaultTitle={siteConfig.title}>
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{language && <html lang={language} />}
{language && <meta name="docsearch:language" content={language} />}
</Helmet>

View file

@ -0,0 +1,61 @@
/**
* 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.
*/
import React from 'react';
import './styles.css';
class Search extends React.Component {
constructor() {
super();
this.state = {
enabled: true,
};
}
componentDidMount() {
const {siteConfig = {}, metadata = {}} = this.props;
const {version: thisVersion, language: thisLanguage} = metadata;
const {algolia} = siteConfig;
// https://github.com/algolia/docsearch/issues/352
const isClient = typeof window !== 'undefined';
if (isClient) {
import('docsearch.js').then(({default: docsearch}) => {
docsearch({
appId: algolia.appId,
apiKey: algolia.apiKey,
indexName: algolia.indexName,
inputSelector: '#search_input_react',
algoliaOptions: JSON.parse(
JSON.stringify(algolia.algoliaOptions)
.replace('VERSION', thisVersion)
.replace('LANGUAGE', thisLanguage),
),
});
});
} else {
console.warn('Search has failed to load and now is being disabled');
this.setState({enabled: false});
}
}
render() {
const {enabled} = this.state;
return enabled ? (
<input
id="search_input_react"
type="search"
placeholder="Search docs"
aria-label="Search docs"
/>
) : null;
}
}
export default Search;

File diff suppressed because one or more lines are too long