mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +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/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",
|
||||
|
|
|
@ -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 DocusaurusContext from '@docusaurus/context';
|
||||
import DocusaurusContext from './context';
|
||||
|
||||
function useDocusaurusContext() {
|
||||
return useContext(DocusaurusContext);
|
|
@ -6,5 +6,6 @@
|
|||
"rootDir": "src",
|
||||
"outDir": "lib",
|
||||
"noImplicitAny": false,
|
||||
"jsx": "react",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue