mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-04 20:57:17 +02:00
feat(v2): create useBaseURL helper (#1503)
* feat(v2): create withBaseURL helper * typescript & refactor * nits
This commit is contained in:
parent
e3f8785652
commit
3fc3644875
10 changed files with 464 additions and 565 deletions
|
@ -31,6 +31,7 @@
|
||||||
"@types/jest": "^24.0.13",
|
"@types/jest": "^24.0.13",
|
||||||
"@types/lodash": "^4.14.129",
|
"@types/lodash": "^4.14.129",
|
||||||
"@types/node": "^12.0.2",
|
"@types/node": "^12.0.2",
|
||||||
|
"@types/react": "^16.8.18",
|
||||||
"@types/react-dev-utils": "^9.0.1",
|
"@types/react-dev-utils": "^9.0.1",
|
||||||
"@types/shelljs": "^0.8.5",
|
"@types/shelljs": "^0.8.5",
|
||||||
"@types/webpack": "^4.4.31",
|
"@types/webpack": "^4.4.31",
|
||||||
|
|
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
|
@ -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;
|
|
15
packages/docusaurus/src/client/exports/context.ts
Normal file
15
packages/docusaurus/src/client/exports/context.ts
Normal 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>({});
|
28
packages/docusaurus/src/client/exports/useBaseUrl.ts
Normal file
28
packages/docusaurus/src/client/exports/useBaseUrl.ts
Normal 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;
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {useContext} from 'react';
|
import {useContext} from 'react';
|
||||||
import DocusaurusContext from '@docusaurus/context';
|
import DocusaurusContext from './context';
|
||||||
|
|
||||||
function useDocusaurusContext() {
|
function useDocusaurusContext() {
|
||||||
return useContext(DocusaurusContext);
|
return useContext(DocusaurusContext);
|
|
@ -6,5 +6,6 @@
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"outDir": "lib",
|
"outDir": "lib",
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
"jsx": "react",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {useContext} from 'react';
|
import React from 'react';
|
||||||
import Head from '@docusaurus/Head';
|
|
||||||
import DocusaurusContext from '@docusaurus/context';
|
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
|
|
||||||
|
@ -61,13 +61,9 @@ const QUOTES = [
|
||||||
];
|
];
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const context = useContext(DocusaurusContext);
|
const context = useDocusaurusContext();
|
||||||
const {siteConfig = {}} = context;
|
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 (
|
return (
|
||||||
<Layout description={'Docusaurus makes it easy to build websites'}>
|
<Layout description={'Docusaurus makes it easy to build websites'}>
|
||||||
<div className={styles['index-hero']}>
|
<div className={styles['index-hero']}>
|
||||||
|
@ -76,7 +72,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt="Docusaurus with Keytar"
|
alt="Docusaurus with Keytar"
|
||||||
className={styles['index-hero-logo']}
|
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{' '}
|
{siteConfig.title} makes it easy to maintain{' '}
|
||||||
<span className={styles['index-hero-project-keywords']}>
|
<span className={styles['index-hero-project-keywords']}>
|
||||||
|
@ -87,7 +83,7 @@ function Home() {
|
||||||
<div className={styles['index-ctas']}>
|
<div className={styles['index-ctas']}>
|
||||||
<Link
|
<Link
|
||||||
className={styles['index-ctas-get-started-button']}
|
className={styles['index-ctas-get-started-button']}
|
||||||
to={gettingStartedUrl}>
|
to={useBaseUrl('docs/introduction')}>
|
||||||
Get Started
|
Get Started
|
||||||
</Link>
|
</Link>
|
||||||
<span className={styles['index-ctas-github-button']}>
|
<span className={styles['index-ctas-github-button']}>
|
||||||
|
@ -110,7 +106,7 @@ function Home() {
|
||||||
Docusaurus 2
|
Docusaurus 2
|
||||||
</a>
|
</a>
|
||||||
, contribute to its roadmap by suggesting features or giving{' '}
|
, 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>
|
</div>
|
||||||
<div className={styles.section}>
|
<div className={styles.section}>
|
||||||
|
@ -120,7 +116,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
className={styles.featureImage}
|
className={styles.featureImage}
|
||||||
alt={'Powered by Markdown'}
|
alt={'Powered by Markdown'}
|
||||||
src={`${siteConfig.baseUrl}img/undraw_typewriter.svg`}
|
src={useBaseUrl('img/undraw_typewriter.svg')}
|
||||||
/>
|
/>
|
||||||
<h3>Powered by Markdown</h3>
|
<h3>Powered by Markdown</h3>
|
||||||
<p className="padding-horiz--md">
|
<p className="padding-horiz--md">
|
||||||
|
@ -133,7 +129,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt={'Built Using React'}
|
alt={'Built Using React'}
|
||||||
className={styles.featureImage}
|
className={styles.featureImage}
|
||||||
src={`${siteConfig.baseUrl}img/undraw_react.svg`}
|
src={useBaseUrl('img/undraw_react.svg')}
|
||||||
/>
|
/>
|
||||||
<h3>Built Using React</h3>
|
<h3>Built Using React</h3>
|
||||||
<p className="padding-horiz--md">
|
<p className="padding-horiz--md">
|
||||||
|
@ -146,7 +142,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt={'Ready for Translations'}
|
alt={'Ready for Translations'}
|
||||||
className={styles.featureImage}
|
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>
|
<h3>Ready for Translations</h3>
|
||||||
<p className="padding-horiz--md">
|
<p className="padding-horiz--md">
|
||||||
|
@ -162,7 +158,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt={'Document Versioning'}
|
alt={'Document Versioning'}
|
||||||
className={styles.featureImage}
|
className={styles.featureImage}
|
||||||
src={`${siteConfig.baseUrl}img/undraw_version_control.svg`}
|
src={useBaseUrl('img/undraw_version_control.svg')}
|
||||||
/>
|
/>
|
||||||
<h3>Document Versioning</h3>
|
<h3>Document Versioning</h3>
|
||||||
<p className="padding-horiz--md">
|
<p className="padding-horiz--md">
|
||||||
|
@ -175,7 +171,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt={'Document Search'}
|
alt={'Document Search'}
|
||||||
className={styles.featureImage}
|
className={styles.featureImage}
|
||||||
src={`${siteConfig.baseUrl}img/undraw_algolia.svg`}
|
src={useBaseUrl('img/undraw_algolia.svg')}
|
||||||
/>
|
/>
|
||||||
<h3>Document Search</h3>
|
<h3>Document Search</h3>
|
||||||
<p className="padding-horiz--md">
|
<p className="padding-horiz--md">
|
||||||
|
@ -200,7 +196,7 @@ function Home() {
|
||||||
<img
|
<img
|
||||||
alt={quote.name}
|
alt={quote.name}
|
||||||
className="avatar__photo avatar__photo--xl"
|
className="avatar__photo avatar__photo--xl"
|
||||||
src={`${siteConfig.baseUrl}${quote.thumbnail}`}
|
src={useBaseUrl(quote.thumbnail)}
|
||||||
/>
|
/>
|
||||||
<div className="avatar__intro">
|
<div className="avatar__intro">
|
||||||
<h4 className="avatar__name">{quote.name}</h4>
|
<h4 className="avatar__name">{quote.name}</h4>
|
||||||
|
|
Loading…
Add table
Reference in a new issue