mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
feat: custom pages (#994)
This commit is contained in:
parent
7d4d9fe961
commit
8691a2525c
25 changed files with 263 additions and 128 deletions
|
@ -83,7 +83,6 @@ module.exports = async function start(siteDir, cliOptions = {}) {
|
||||||
const compiler = webpack(config);
|
const compiler = webpack(config);
|
||||||
|
|
||||||
// webpack-serve
|
// webpack-serve
|
||||||
setTimeout(async () => {
|
|
||||||
await serve(
|
await serve(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -120,5 +119,4 @@ module.exports = async function start(siteDir, cliOptions = {}) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}, 1000);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,7 +49,7 @@ module.exports = async function load(siteDir) {
|
||||||
|
|
||||||
// pages
|
// pages
|
||||||
const pagesDir = path.resolve(siteDir, 'pages');
|
const pagesDir = path.resolve(siteDir, 'pages');
|
||||||
const pagesMetadatas = await loadPages(pagesDir);
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
await generate(
|
await generate(
|
||||||
'pagesMetadatas.js',
|
'pagesMetadatas.js',
|
||||||
`export default ${JSON.stringify(pagesMetadatas, null, 2)};`,
|
`export default ${JSON.stringify(pagesMetadatas, null, 2)};`,
|
||||||
|
|
|
@ -1,16 +1,57 @@
|
||||||
const globby = require('globby');
|
const globby = require('globby');
|
||||||
const {encodePath, fileToPath} = require('./utils');
|
const path = require('path');
|
||||||
|
const {encodePath, fileToPath, idx} = require('./utils');
|
||||||
|
|
||||||
async function loadPages(pagesDir) {
|
async function loadPages({pagesDir, env, siteConfig}) {
|
||||||
const pagesFiles = await globby(['**/*.js'], {
|
const pagesFiles = await globby(['**/*.js'], {
|
||||||
cwd: pagesDir,
|
cwd: pagesDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
const pagesMetadatas = await Promise.all(
|
const {baseUrl} = siteConfig;
|
||||||
pagesFiles.map(async source => ({
|
|
||||||
path: encodePath(fileToPath(source)),
|
/* Prepare metadata container */
|
||||||
|
const pagesMetadatas = [];
|
||||||
|
|
||||||
|
/* Translation */
|
||||||
|
const translationEnabled = idx(env, ['translation', 'enabled']);
|
||||||
|
const enabledLanguages =
|
||||||
|
translationEnabled && idx(env, ['translation', 'enabledLanguages']);
|
||||||
|
const enabledLangTags =
|
||||||
|
(enabledLanguages && enabledLanguages.map(lang => lang.tag)) || [];
|
||||||
|
const defaultLangTag = idx(env, ['translation', 'defaultLanguage', 'tag']);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
pagesFiles.map(async relativeSource => {
|
||||||
|
const source = path.join(pagesDir, relativeSource);
|
||||||
|
const pathName = encodePath(fileToPath(relativeSource));
|
||||||
|
if (translationEnabled && enabledLangTags.length > 0) {
|
||||||
|
enabledLangTags.forEach(langTag => {
|
||||||
|
/* default lang should also be available. E.g: /en/users and /users is the same */
|
||||||
|
if (langTag === defaultLangTag) {
|
||||||
|
pagesMetadatas.push({
|
||||||
|
permalink: pathName.replace(/^\//, baseUrl),
|
||||||
|
language: langTag,
|
||||||
source,
|
source,
|
||||||
})),
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata = {
|
||||||
|
permalink: pathName.replace(/^\//, `${baseUrl}${langTag}/`),
|
||||||
|
language: langTag,
|
||||||
|
source,
|
||||||
|
};
|
||||||
|
pagesMetadatas.push(metadata);
|
||||||
|
});
|
||||||
|
|
||||||
|
// for defaultLanguage
|
||||||
|
} else {
|
||||||
|
const metadata = {
|
||||||
|
permalink: pathName.replace(/^\//, baseUrl),
|
||||||
|
source,
|
||||||
|
};
|
||||||
|
pagesMetadatas.push(metadata);
|
||||||
|
}
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
return pagesMetadatas;
|
return pagesMetadatas;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,23 @@ async function genRoutesConfig({docsMetadatas = {}, pagesMetadatas = []}) {
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function genPagesRoute({path: pagesPath, source}) {
|
function genPagesRoute(metadata) {
|
||||||
|
const {permalink, source} = metadata;
|
||||||
return `
|
return `
|
||||||
{
|
{
|
||||||
path: ${JSON.stringify(pagesPath)},
|
path: ${JSON.stringify(permalink)},
|
||||||
exact: true,
|
exact: true,
|
||||||
component: Loadable({
|
component: Loadable({
|
||||||
loader: () => import('@pages/${source}'),
|
loader: () => import(${JSON.stringify(source)}),
|
||||||
loading: Loading
|
loading: Loading,
|
||||||
|
render(loaded, props) {
|
||||||
|
let Content = loaded.default;
|
||||||
|
return (
|
||||||
|
<Pages {...props} metadata={${JSON.stringify(metadata)}}>
|
||||||
|
<Content {...props} metadata={${JSON.stringify(metadata)}} />
|
||||||
|
</Pages>
|
||||||
|
);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +56,7 @@ async function genRoutesConfig({docsMetadatas = {}, pagesMetadatas = []}) {
|
||||||
`import Loadable from 'react-loadable';\n` +
|
`import Loadable from 'react-loadable';\n` +
|
||||||
`import Loading from '@theme/Loading';\n` +
|
`import Loading from '@theme/Loading';\n` +
|
||||||
`import Docs from '@theme/Docs';\n` +
|
`import Docs from '@theme/Docs';\n` +
|
||||||
|
`import Pages from '@theme/Pages';\n` +
|
||||||
`import NotFound from '@theme/NotFound';\n` +
|
`import NotFound from '@theme/NotFound';\n` +
|
||||||
`const routes = [${docsRoutes},${pagesMetadatas
|
`const routes = [${docsRoutes},${pagesMetadatas
|
||||||
.map(genPagesRoute)
|
.map(genPagesRoute)
|
||||||
|
|
|
@ -7,7 +7,7 @@ module.exports = function loadConfig(siteDir) {
|
||||||
? customThemePath
|
? customThemePath
|
||||||
: path.resolve(__dirname, '../theme');
|
: path.resolve(__dirname, '../theme');
|
||||||
|
|
||||||
const themeComponents = ['Docs', 'Loading', 'NotFound', 'Markdown'];
|
const themeComponents = ['Docs', 'Pages', 'Loading', 'NotFound', 'Markdown'];
|
||||||
themeComponents.forEach(component => {
|
themeComponents.forEach(component => {
|
||||||
if (!require.resolve(path.join(themePath, component))) {
|
if (!require.resolve(path.join(themePath, component))) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
@ -52,10 +52,14 @@ export default class Docs extends React.Component {
|
||||||
docsSidebars,
|
docsSidebars,
|
||||||
metadata,
|
metadata,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const {language, version} = metadata;
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<Layout {...this.props}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{(metadata && metadata.title) || siteConfig.title}</title>
|
<title>{(metadata && metadata.title) || siteConfig.title}</title>
|
||||||
|
{language && <html lang={language} />}
|
||||||
|
{language && <meta name="docsearch:language" content={language} />}
|
||||||
|
{version && <meta name="docsearch:version" content={version} />}
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>{this.renderSidebar(metadata, docsSidebars, docsMetadatas)}</div>
|
<div>{this.renderSidebar(metadata, docsSidebars, docsMetadatas)}</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -5,15 +5,18 @@ import styles from './styles.css';
|
||||||
/* eslint-disable react/prefer-stateless-function */
|
/* eslint-disable react/prefer-stateless-function */
|
||||||
export default class Layout extends React.Component {
|
export default class Layout extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const {children, pagesMetadatas, docsMetadatas = {}, location} = this.props;
|
const {
|
||||||
const docsLinks = Object.values(docsMetadatas).map(data => ({
|
children,
|
||||||
path: `${data.permalink}`,
|
pagesMetadatas = [],
|
||||||
}));
|
docsMetadatas = {},
|
||||||
const routeLinks = [...pagesMetadatas, ...docsLinks].map(
|
location,
|
||||||
|
} = this.props;
|
||||||
|
const docsFlatMetadatas = Object.values(docsMetadatas);
|
||||||
|
const routeLinks = [...pagesMetadatas, ...docsFlatMetadatas].map(
|
||||||
data =>
|
data =>
|
||||||
data.path !== location.pathname && (
|
data.permalink !== location.pathname && (
|
||||||
<li key={data.path}>
|
<li key={data.permalink}>
|
||||||
<Link to={data.path}>{data.path}</Link>
|
<Link to={data.permalink}>{data.permalink}</Link>
|
||||||
</li>
|
</li>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
21
v2/lib/theme/Pages/index.js
Normal file
21
v2/lib/theme/Pages/index.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* eslint-disable */
|
||||||
|
import React from 'react';
|
||||||
|
import {Link} from 'react-router-dom';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
import Layout from '@theme/Layout'; // eslint-disable-line
|
||||||
|
|
||||||
|
export default class Pages extends React.Component {
|
||||||
|
render() {
|
||||||
|
const {metadata, children, siteConfig} = this.props;
|
||||||
|
const {language} = metadata;
|
||||||
|
return (
|
||||||
|
<Layout {...this.props}>
|
||||||
|
<Helmet defaultTitle={siteConfig.title}>
|
||||||
|
{language && <html lang={language} />}
|
||||||
|
{language && <meta name="docsearch:language" content={language} />}
|
||||||
|
</Helmet>
|
||||||
|
{children}
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,10 @@ module.exports = function createServerConfig(props) {
|
||||||
const {siteConfig, docsMetadatas, pagesMetadatas} = props;
|
const {siteConfig, docsMetadatas, pagesMetadatas} = props;
|
||||||
|
|
||||||
// static site generator webpack plugin
|
// static site generator webpack plugin
|
||||||
const docsLinks = Object.values(docsMetadatas).map(data => ({
|
const docsFlatMetadatas = Object.values(docsMetadatas);
|
||||||
path: `${data.permalink}`,
|
const paths = [...docsFlatMetadatas, ...pagesMetadatas].map(
|
||||||
}));
|
data => data.permalink,
|
||||||
const paths = [...docsLinks, ...pagesMetadatas].map(data => data.path);
|
);
|
||||||
config.plugin('siteGenerator').use(staticSiteGenerator, [
|
config.plugin('siteGenerator').use(staticSiteGenerator, [
|
||||||
{
|
{
|
||||||
entry: 'main',
|
entry: 'main',
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class World extends React.Component {
|
export default class World extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>World</title>
|
<title>World</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Hello World </div>
|
<div>Hello World </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Home ... </div>
|
<div>Home ... </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class World extends React.Component {
|
export default class World extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>World</title>
|
<title>World</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Hello World </div>
|
<div>Hello World </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Home ... </div>
|
<div>Home ... </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class World extends React.Component {
|
export default class World extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>World</title>
|
<title>World</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Hello World </div>
|
<div>Hello World </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Home ... </div>
|
<div>Home ... </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class World extends React.Component {
|
export default class World extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>World</title>
|
<title>World</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Hello World </div>
|
<div>Hello World </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div>Home ... </div>
|
<div>Home ... </div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default () => <div>Baz</div>;
|
|
|
@ -1,3 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default () => <div>Foo</div>;
|
|
|
@ -1,3 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default () => <div>Foo in subfolder</div>;
|
|
|
@ -1,3 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default () => <div>Index</div>;
|
|
|
@ -1,35 +1,116 @@
|
||||||
import loadPages from '@lib/load/pages';
|
import loadPages from '@lib/load/pages';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import loadSetup from '../loadSetup';
|
||||||
|
|
||||||
describe('loadPages', () => {
|
describe('loadPages', () => {
|
||||||
test('valid pages', async () => {
|
test('simple website', async () => {
|
||||||
const pagesDir = path.join(__dirname, '__fixtures__', 'simple-pages');
|
const {pagesDir, env, siteConfig} = await loadSetup('simple');
|
||||||
const pagesMetadatas = await loadPages(pagesDir);
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
pagesMetadatas.sort((a, b) => a.path > b.path); // because it was unordered
|
|
||||||
expect(pagesMetadatas).toEqual([
|
expect(pagesMetadatas).toEqual([
|
||||||
{
|
{
|
||||||
path: '/',
|
permalink: '/',
|
||||||
source: 'index.js',
|
source: path.join(pagesDir, 'index.js'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/bar/baz',
|
permalink: '/hello/world',
|
||||||
source: 'bar/baz.js',
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
},
|
},
|
||||||
{
|
]);
|
||||||
path: '/foo',
|
});
|
||||||
source: 'foo.js',
|
|
||||||
},
|
test('versioned website', async () => {
|
||||||
{
|
const {pagesDir, env, siteConfig} = await loadSetup('versioned');
|
||||||
path: '/foo/',
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
source: 'foo/index.js',
|
expect(pagesMetadatas).toEqual([
|
||||||
|
{
|
||||||
|
permalink: '/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permalink: '/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('versioned & translated website', async () => {
|
||||||
|
const {pagesDir, env, siteConfig} = await loadSetup('transversioned');
|
||||||
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
|
expect(pagesMetadatas).toEqual([
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/en/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'ko',
|
||||||
|
permalink: '/ko/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/en/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'ko',
|
||||||
|
permalink: '/ko/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('translated website', async () => {
|
||||||
|
const {pagesDir, env, siteConfig} = await loadSetup('translated');
|
||||||
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
|
expect(pagesMetadatas).toEqual([
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/en/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'ko',
|
||||||
|
permalink: '/ko/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'en',
|
||||||
|
permalink: '/en/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'ko',
|
||||||
|
permalink: '/ko/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pagesMetadatas).not.toBeNull();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('invalid pages', async () => {
|
test('invalid pages', async () => {
|
||||||
const nonExistingDir = path.join(__dirname, '__fixtures__', 'nonExisting');
|
const {env, siteConfig} = await loadSetup('simple');
|
||||||
const pagesMetadatas = await loadPages(nonExistingDir);
|
const pagesDir = path.join(__dirname, '__fixtures__', 'nonExisting');
|
||||||
|
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
||||||
expect(pagesMetadatas).toEqual([]);
|
expect(pagesMetadatas).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
import Todo from '@site/components/Todo';
|
import Todo from '@site/components/Todo';
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Todo App</title>
|
<title>Todo App</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Todo />
|
<Todo />
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
import Tictactoe from '@site/components/Tictactoe';
|
import Tictactoe from '@site/components/Tictactoe';
|
||||||
|
|
||||||
export default class Home extends React.Component {
|
export default class Home extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Tic Tac Toe</title>
|
<title>Tic Tac Toe</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Tictactoe />
|
<Tictactoe />
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import YouTube from 'react-youtube';
|
import YouTube from 'react-youtube';
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
|
|
||||||
export default class Player extends React.Component {
|
export default class Player extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -14,15 +13,15 @@ export default class Player extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout {...this.props}>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>My Youtube</title>
|
<title>My Youtube</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<p align="center">
|
<div align="center">
|
||||||
{/* this is a React-youtube component */}
|
{/* this is a React-youtube component */}
|
||||||
<YouTube videoId="d9IxdwEFk1c" opts={opts} onReady={this._onReady} />
|
<YouTube videoId="d9IxdwEFk1c" opts={opts} onReady={this._onReady} />
|
||||||
</p>
|
</div>
|
||||||
</Layout>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue