feat(v2): create useBaseURL helper (#1503)

* feat(v2): create withBaseURL helper

* typescript & refactor

* nits
This commit is contained in:
Yangshun Tay 2019-05-22 03:32:52 -07:00 committed by Endi
parent e3f8785652
commit 3fc3644875
10 changed files with 464 additions and 565 deletions

View file

@ -31,6 +31,7 @@
"@types/jest": "^24.0.13",
"@types/lodash": "^4.14.129",
"@types/node": "^12.0.2",
"@types/react": "^16.8.18",
"@types/react-dev-utils": "^9.0.1",
"@types/shelljs": "^0.8.5",
"@types/webpack": "^4.4.31",

View file

@ -0,0 +1,52 @@
/**
* 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 useBaseUrl from '../useBaseUrl';
import useDocusaurusContext from '../useDocusaurusContext';
jest.mock('../useDocusaurusContext', () => jest.fn(), {virtual: true});
const mockedContext = <jest.Mock>useDocusaurusContext;
describe('useBaseURL', () => {
test('empty base URL', () => {
mockedContext.mockImplementation(() => ({
siteConfig: {
baseUrl: '/',
},
}));
expect(useBaseUrl('hello')).toEqual('/hello');
expect(useBaseUrl('/hello')).toEqual('/hello');
expect(useBaseUrl('hello/')).toEqual('/hello/');
expect(useBaseUrl('/hello/')).toEqual('/hello/');
expect(useBaseUrl('hello/byebye')).toEqual('/hello/byebye');
expect(useBaseUrl('/hello/byebye')).toEqual('/hello/byebye');
expect(useBaseUrl('hello/byebye/')).toEqual('/hello/byebye/');
expect(useBaseUrl('/hello/byebye/')).toEqual('/hello/byebye/');
expect(useBaseUrl('https://github.com')).toEqual('https://github.com');
expect(useBaseUrl('//reactjs.org')).toEqual('//reactjs.org');
});
test('non-empty base URL', () => {
mockedContext.mockImplementation(() => ({
siteConfig: {
baseUrl: '/docusaurus/',
},
}));
expect(useBaseUrl('hello')).toEqual('/docusaurus/hello');
expect(useBaseUrl('/hello')).toEqual('/docusaurus/hello');
expect(useBaseUrl('hello/')).toEqual('/docusaurus/hello/');
expect(useBaseUrl('/hello/')).toEqual('/docusaurus/hello/');
expect(useBaseUrl('hello/byebye')).toEqual('/docusaurus/hello/byebye');
expect(useBaseUrl('/hello/byebye')).toEqual('/docusaurus/hello/byebye');
expect(useBaseUrl('hello/byebye/')).toEqual('/docusaurus/hello/byebye/');
expect(useBaseUrl('/hello/byebye/')).toEqual('/docusaurus/hello/byebye/');
expect(useBaseUrl('https://github.com')).toEqual('https://github.com');
expect(useBaseUrl('//reactjs.org')).toEqual('//reactjs.org');
});
});

View file

@ -1,12 +0,0 @@
/**
* 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';
const DocusaurusContext = React.createContext({});
export default DocusaurusContext;

View file

@ -0,0 +1,15 @@
/**
* 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 * as React from 'react';
import {DocusaurusConfig} from '../../server/config';
export interface DocusaurusContext {
siteConfig?: DocusaurusConfig;
}
export default React.createContext<DocusaurusContext>({});

View file

@ -0,0 +1,28 @@
/**
* 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 useDocusaurusContext from './useDocusaurusContext';
export function withBaseUrl(baseUrl: string, url: string): string {
if (url.startsWith('/')) {
return baseUrl + url.slice(1);
}
return baseUrl + url;
}
function useBaseUrl(url: string): string {
const {siteConfig} = useDocusaurusContext();
const {baseUrl = '/'} = siteConfig || {};
const externalRegex = /^(https?:|\/\/)/;
if (externalRegex.test(url)) {
return url;
}
return withBaseUrl(baseUrl, url);
}
export default useBaseUrl;

View file

@ -6,7 +6,7 @@
*/
import {useContext} from 'react';
import DocusaurusContext from '@docusaurus/context';
import DocusaurusContext from './context';
function useDocusaurusContext() {
return useContext(DocusaurusContext);

View file

@ -6,5 +6,6 @@
"rootDir": "src",
"outDir": "lib",
"noImplicitAny": false,
"jsx": "react",
},
}

View file

@ -5,10 +5,10 @@
* LICENSE file in the root directory of this source tree.
*/
import React, {useContext} from 'react';
import Head from '@docusaurus/Head';
import DocusaurusContext from '@docusaurus/context';
import React from 'react';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import Layout from '@theme/Layout';
@ -61,13 +61,9 @@ const QUOTES = [
];
function Home() {
const context = useContext(DocusaurusContext);
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
// TODO: (wrapper function) API so that user won't need to concatenate url manually
const feedbackUrl = `${siteConfig.baseUrl}feedback/`;
const gettingStartedUrl = `${siteConfig.baseUrl}docs/introduction`;
return (
<Layout description={'Docusaurus makes it easy to build websites'}>
<div className={styles['index-hero']}>
@ -76,7 +72,7 @@ function Home() {
<img
alt="Docusaurus with Keytar"
className={styles['index-hero-logo']}
src={`${siteConfig.baseUrl}img/docusaurus_keytar.svg`}
src={useBaseUrl('img/docusaurus_keytar.svg')}
/>
{siteConfig.title} makes it easy to maintain{' '}
<span className={styles['index-hero-project-keywords']}>
@ -87,7 +83,7 @@ function Home() {
<div className={styles['index-ctas']}>
<Link
className={styles['index-ctas-get-started-button']}
to={gettingStartedUrl}>
to={useBaseUrl('docs/introduction')}>
Get Started
</Link>
<span className={styles['index-ctas-github-button']}>
@ -110,7 +106,7 @@ function Home() {
Docusaurus 2
</a>
, contribute to its roadmap by suggesting features or giving{' '}
<Link to={feedbackUrl}>feedback here</Link>!
<Link to={useBaseUrl('/feedback')}>feedback here</Link>!
</div>
</div>
<div className={styles.section}>
@ -120,7 +116,7 @@ function Home() {
<img
className={styles.featureImage}
alt={'Powered by Markdown'}
src={`${siteConfig.baseUrl}img/undraw_typewriter.svg`}
src={useBaseUrl('img/undraw_typewriter.svg')}
/>
<h3>Powered by Markdown</h3>
<p className="padding-horiz--md">
@ -133,7 +129,7 @@ function Home() {
<img
alt={'Built Using React'}
className={styles.featureImage}
src={`${siteConfig.baseUrl}img/undraw_react.svg`}
src={useBaseUrl('img/undraw_react.svg')}
/>
<h3>Built Using React</h3>
<p className="padding-horiz--md">
@ -146,7 +142,7 @@ function Home() {
<img
alt={'Ready for Translations'}
className={styles.featureImage}
src={`${siteConfig.baseUrl}img/undraw_around_the_world.svg`}
src={useBaseUrl('img/undraw_around_the_world.svg')}
/>
<h3>Ready for Translations</h3>
<p className="padding-horiz--md">
@ -162,7 +158,7 @@ function Home() {
<img
alt={'Document Versioning'}
className={styles.featureImage}
src={`${siteConfig.baseUrl}img/undraw_version_control.svg`}
src={useBaseUrl('img/undraw_version_control.svg')}
/>
<h3>Document Versioning</h3>
<p className="padding-horiz--md">
@ -175,7 +171,7 @@ function Home() {
<img
alt={'Document Search'}
className={styles.featureImage}
src={`${siteConfig.baseUrl}img/undraw_algolia.svg`}
src={useBaseUrl('img/undraw_algolia.svg')}
/>
<h3>Document Search</h3>
<p className="padding-horiz--md">
@ -200,7 +196,7 @@ function Home() {
<img
alt={quote.name}
className="avatar__photo avatar__photo--xl"
src={`${siteConfig.baseUrl}${quote.thumbnail}`}
src={useBaseUrl(quote.thumbnail)}
/>
<div className="avatar__intro">
<h4 className="avatar__name">{quote.name}</h4>

888
yarn.lock

File diff suppressed because it is too large Load diff