mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-07 03:48:01 +02:00
feat(v2): pluginify pages (#1278)
* feat(v2): convert pages into a plugin * fix: update tests
This commit is contained in:
parent
2da59ed4af
commit
398d7c7ae4
21 changed files with 287 additions and 257 deletions
|
@ -1,4 +1,3 @@
|
||||||
__fixtures__
|
|
||||||
dist
|
dist
|
||||||
node_modules
|
node_modules
|
||||||
build
|
build
|
||||||
|
|
|
@ -37,5 +37,8 @@ module.exports = {
|
||||||
path: '../v1/website/blog',
|
path: '../v1/website/blog',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,6 @@ const path = require('path');
|
||||||
const loadConfig = require('./config');
|
const loadConfig = require('./config');
|
||||||
const loadDocs = require('./docs');
|
const loadDocs = require('./docs');
|
||||||
const loadEnv = require('./env');
|
const loadEnv = require('./env');
|
||||||
const loadPages = require('./pages');
|
|
||||||
const loadTheme = require('./theme');
|
const loadTheme = require('./theme');
|
||||||
const {generate} = require('./utils');
|
const {generate} = require('./utils');
|
||||||
const loadRoutes = require('./routes');
|
const loadRoutes = require('./routes');
|
||||||
|
@ -71,25 +70,16 @@ module.exports = async function load(siteDir) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pages.
|
|
||||||
const pagesDir = path.resolve(siteDir, 'pages');
|
|
||||||
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
|
||||||
await generate(
|
|
||||||
generatedFilesDir,
|
|
||||||
'pagesMetadatas.js',
|
|
||||||
`export default ${JSON.stringify(pagesMetadatas, null, 2)};`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Process plugins.
|
// Process plugins.
|
||||||
const pluginConfigs = siteConfig.plugins || [];
|
const pluginConfigs = siteConfig.plugins || [];
|
||||||
const context = {env, siteDir, siteConfig};
|
const context = {env, siteDir, siteConfig};
|
||||||
|
|
||||||
// Initialize plugins.
|
// Initialize plugins.
|
||||||
const plugins = pluginConfigs.map(({name, options: opts}) => {
|
const plugins = pluginConfigs.map(({name, options}) => {
|
||||||
// TODO: Resolve using node_modules as well.
|
// TODO: Resolve using node_modules as well.
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const Plugin = require(path.resolve(__dirname, '../../plugins', name));
|
const Plugin = require(path.resolve(__dirname, '../../plugins', name));
|
||||||
return new Plugin(opts, context);
|
return new Plugin(options, context);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Plugin lifecycle - loadContents().
|
// Plugin lifecycle - loadContents().
|
||||||
|
@ -156,7 +146,6 @@ module.exports = async function load(siteDir) {
|
||||||
const {routesConfig, routesPaths} = await loadRoutes({
|
const {routesConfig, routesPaths} = await loadRoutes({
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsMetadatas,
|
docsMetadatas,
|
||||||
pagesMetadatas,
|
|
||||||
pluginRouteConfigs,
|
pluginRouteConfigs,
|
||||||
});
|
});
|
||||||
await generate(generatedFilesDir, 'routes.js', routesConfig);
|
await generate(generatedFilesDir, 'routes.js', routesConfig);
|
||||||
|
@ -189,10 +178,6 @@ module.exports = async function load(siteDir) {
|
||||||
name: 'docsSidebars',
|
name: 'docsSidebars',
|
||||||
path: '@generated/docsSidebars',
|
path: '@generated/docsSidebars',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'pagesMetadatas',
|
|
||||||
path: '@generated/pagesMetadatas',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
await generate(generatedFilesDir, 'metadata.js', metadataFile);
|
await generate(generatedFilesDir, 'metadata.js', metadataFile);
|
||||||
|
@ -204,8 +189,6 @@ module.exports = async function load(siteDir) {
|
||||||
docsMetadatas,
|
docsMetadatas,
|
||||||
docsSidebars,
|
docsSidebars,
|
||||||
env,
|
env,
|
||||||
pagesDir,
|
|
||||||
pagesMetadatas,
|
|
||||||
outDir,
|
outDir,
|
||||||
themePath,
|
themePath,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
|
|
@ -1,65 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const globby = require('globby');
|
|
||||||
const path = require('path');
|
|
||||||
const {encodePath, fileToPath, idx} = require('./utils');
|
|
||||||
|
|
||||||
async function loadPages({pagesDir, env, siteConfig}) {
|
|
||||||
const pagesFiles = await globby(['**/*.js'], {
|
|
||||||
cwd: pagesDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {baseUrl} = siteConfig;
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata = {
|
|
||||||
permalink: pathName.replace(/^\//, `${baseUrl}${langTag}/`),
|
|
||||||
language: langTag,
|
|
||||||
source,
|
|
||||||
};
|
|
||||||
pagesMetadatas.push(metadata);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Default Language.
|
|
||||||
const metadata = {
|
|
||||||
permalink: pathName.replace(/^\//, baseUrl),
|
|
||||||
source,
|
|
||||||
};
|
|
||||||
pagesMetadatas.push(metadata);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return pagesMetadatas;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = loadPages;
|
|
|
@ -10,7 +10,6 @@ const {normalizeUrl} = require('./utils');
|
||||||
async function loadRoutes({
|
async function loadRoutes({
|
||||||
siteConfig = {},
|
siteConfig = {},
|
||||||
docsMetadatas = {},
|
docsMetadatas = {},
|
||||||
pagesMetadatas = [],
|
|
||||||
pluginRouteConfigs = [],
|
pluginRouteConfigs = [],
|
||||||
}) {
|
}) {
|
||||||
const imports = [
|
const imports = [
|
||||||
|
@ -19,7 +18,6 @@ async function loadRoutes({
|
||||||
`import Loading from '@theme/Loading';`,
|
`import Loading from '@theme/Loading';`,
|
||||||
`import Doc from '@theme/Doc';`,
|
`import Doc from '@theme/Doc';`,
|
||||||
`import DocBody from '@theme/DocBody';`,
|
`import DocBody from '@theme/DocBody';`,
|
||||||
`import Pages from '@theme/Pages';`,
|
|
||||||
`import NotFound from '@theme/NotFound';`,
|
`import NotFound from '@theme/NotFound';`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -64,29 +62,6 @@ async function loadRoutes({
|
||||||
.join(',')}],
|
.join(',')}],
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
// Pages.
|
|
||||||
function genPagesRoute(metadata) {
|
|
||||||
const {permalink, source} = metadata;
|
|
||||||
addRoutesPath(permalink);
|
|
||||||
return `
|
|
||||||
{
|
|
||||||
path: '${permalink}',
|
|
||||||
exact: true,
|
|
||||||
component: Loadable({
|
|
||||||
loader: () => import('${source}'),
|
|
||||||
loading: Loading,
|
|
||||||
render(loaded, props) {
|
|
||||||
let Content = loaded.default;
|
|
||||||
return (
|
|
||||||
<Pages {...props} metadata={${JSON.stringify(metadata)}}>
|
|
||||||
<Content {...props} metadata={${JSON.stringify(metadata)}} />
|
|
||||||
</Pages>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const notFoundRoute = `
|
const notFoundRoute = `
|
||||||
{
|
{
|
||||||
path: '*',
|
path: '*',
|
||||||
|
@ -131,9 +106,7 @@ ${modules
|
||||||
${imports.join('\n')}
|
${imports.join('\n')}
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// Docs.${pagesMetadatas.map(genPagesRoute).join(',')},
|
// Docs.${docsRoutes},
|
||||||
|
|
||||||
// Pages.${docsRoutes},
|
|
||||||
|
|
||||||
// Plugins.${routes.join(',')},
|
// Plugins.${routes.join(',')},
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@ import styles from './styles.module.css';
|
||||||
|
|
||||||
function Footer() {
|
function Footer() {
|
||||||
const context = useContext(DocusaurusContext);
|
const context = useContext(DocusaurusContext);
|
||||||
const {pagesMetadatas} = context;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
<section className={styles.footerRow}>
|
<section className={styles.footerRow}>
|
||||||
|
@ -79,11 +77,11 @@ function Footer() {
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/* This is for v2 development only to know which are the available page */}
|
{/* This is for v2 development only to know the available pages. */}
|
||||||
<div className={styles.footerColumn}>
|
<div className={styles.footerColumn}>
|
||||||
<h3 className={styles.footerColumnTitle}>Pages</h3>
|
<h3 className={styles.footerColumnTitle}>Pages</h3>
|
||||||
<ul className={styles.footerList}>
|
<ul className={styles.footerList}>
|
||||||
{pagesMetadatas.map(metadata => (
|
{context.pagesMetadata.map(metadata => (
|
||||||
<li key={metadata.permalink} className={styles.footerListItem}>
|
<li key={metadata.permalink} className={styles.footerListItem}>
|
||||||
<Link className={styles.footerLink} to={metadata.permalink}>
|
<Link className={styles.footerLink} to={metadata.permalink}>
|
||||||
{metadata.permalink}
|
{metadata.permalink}
|
||||||
|
|
|
@ -12,11 +12,12 @@ import Layout from '@theme/Layout'; // eslint-disable-line
|
||||||
|
|
||||||
import DocusaurusContext from '@docusaurus/context';
|
import DocusaurusContext from '@docusaurus/context';
|
||||||
|
|
||||||
function Pages({children}) {
|
function Pages({modules}) {
|
||||||
const context = useContext(DocusaurusContext);
|
const context = useContext(DocusaurusContext);
|
||||||
const {metadata = {}, siteConfig = {}} = context;
|
const {metadata = {}, siteConfig = {}} = context;
|
||||||
const {baseUrl, favicon} = siteConfig;
|
const {baseUrl, favicon} = siteConfig;
|
||||||
const {language} = metadata;
|
const {language} = metadata;
|
||||||
|
const PageContents = modules[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
|
@ -25,7 +26,7 @@ function Pages({children}) {
|
||||||
{language && <html lang={language} />}
|
{language && <html lang={language} />}
|
||||||
{language && <meta name="docsearch:language" content={language} />}
|
{language && <meta name="docsearch:language" content={language} />}
|
||||||
</Head>
|
</Head>
|
||||||
{children}
|
<PageContents />
|
||||||
<Footer />
|
<Footer />
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,7 +40,6 @@ module.exports = function createBaseConfig(props, isServer) {
|
||||||
outDir,
|
outDir,
|
||||||
themePath,
|
themePath,
|
||||||
docsDir,
|
docsDir,
|
||||||
pagesDir,
|
|
||||||
siteDir,
|
siteDir,
|
||||||
sourceToMetadata,
|
sourceToMetadata,
|
||||||
versionedDir,
|
versionedDir,
|
||||||
|
@ -69,7 +68,6 @@ module.exports = function createBaseConfig(props, isServer) {
|
||||||
.set('@versioned_docs', versionedDir)
|
.set('@versioned_docs', versionedDir)
|
||||||
.set('@translated_docs', translatedDir)
|
.set('@translated_docs', translatedDir)
|
||||||
.set('@docs', docsDir)
|
.set('@docs', docsDir)
|
||||||
.set('@pages', pagesDir)
|
|
||||||
.set('@build', outDir)
|
.set('@build', outDir)
|
||||||
.set('@generated', generatedFilesDir)
|
.set('@generated', generatedFilesDir)
|
||||||
.set('@core', path.resolve(__dirname, '../core'))
|
.set('@core', path.resolve(__dirname, '../core'))
|
||||||
|
@ -106,7 +104,7 @@ module.exports = function createBaseConfig(props, isServer) {
|
||||||
.end();
|
.end();
|
||||||
applyBabel(jsRule);
|
applyBabel(jsRule);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Equivalent to:
|
Equivalent to:
|
||||||
// ...
|
// ...
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docusaurus": "node bin/docusaurus",
|
"docusaurus": "node bin/docusaurus",
|
||||||
"start": "yarn docusaurus start ../v2-website",
|
"start": "yarn docusaurus start ../v2-website",
|
||||||
"prettier": "prettier --config ../.prettierrc --write \"**/*.js\"",
|
"prettier": "prettier --config ../.prettierrc --ignore-path ../.prettierignore --write \"**/*.js\"",
|
||||||
"lint": "eslint --cache \"{lib,bin,test}/**/*.js\"",
|
"lint": "eslint --cache \"{lib,bin,test,plugins}/**/*.js\"",
|
||||||
"test": "jest --config test/jest.config.js"
|
"test": "jest --config test/jest.config.js"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const globby = require('globby');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
// TODO: Do not make it relative because plugins can be from node_modules.
|
// TODO: Do not make it relative because plugins can be from node_modules.
|
||||||
const {parse, idx, normalizeUrl} = require('../lib/load/utils');
|
const {parse, idx, normalizeUrl} = require('../../lib/load/utils');
|
||||||
|
|
||||||
function fileToUrl(fileName) {
|
function fileToUrl(fileName) {
|
||||||
return fileName
|
return fileName
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* 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 path from 'path';
|
||||||
|
|
||||||
|
import loadSetup from '@test/loadSetup';
|
||||||
|
import DocusaurusPluginContentPages from '../index';
|
||||||
|
|
||||||
|
describe('docusaurus-plugin-content-pages', () => {
|
||||||
|
describe('loadContents', () => {
|
||||||
|
test.each([
|
||||||
|
[
|
||||||
|
'simple',
|
||||||
|
pagesDir => [
|
||||||
|
{
|
||||||
|
permalink: '/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permalink: '/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'versioned',
|
||||||
|
pagesDir => [
|
||||||
|
{
|
||||||
|
permalink: '/',
|
||||||
|
source: path.join(pagesDir, 'index.js'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permalink: '/hello/world',
|
||||||
|
source: path.join(pagesDir, 'hello', 'world.js'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'translated',
|
||||||
|
pagesDir => [
|
||||||
|
{
|
||||||
|
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'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'transversioned',
|
||||||
|
pagesDir => [
|
||||||
|
{
|
||||||
|
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'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
])('%s website', async (type, expected) => {
|
||||||
|
const {env, siteDir, siteConfig} = await loadSetup(type);
|
||||||
|
const plugin = new DocusaurusPluginContentPages(null, {
|
||||||
|
env,
|
||||||
|
siteDir,
|
||||||
|
siteConfig,
|
||||||
|
});
|
||||||
|
const pagesMetadatas = await plugin.loadContents();
|
||||||
|
const pagesDir = plugin.contentPath;
|
||||||
|
|
||||||
|
expect(pagesMetadatas).toEqual(expected(pagesDir));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
112
v2/plugins/docusaurus-plugin-content-pages/index.js
Normal file
112
v2/plugins/docusaurus-plugin-content-pages/index.js
Normal file
|
@ -0,0 +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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const globby = require('globby');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// TODO: Do not make it relative because plugins can be from node_modules.
|
||||||
|
const {encodePath, fileToPath, idx} = require('../../lib/load/utils');
|
||||||
|
|
||||||
|
const DEFAULT_OPTIONS = {
|
||||||
|
metadataKey: 'pagesMetadata',
|
||||||
|
metadataFileName: 'pagesMetadata.json',
|
||||||
|
path: 'pages', // Path to data on filesystem.
|
||||||
|
routeBasePath: '', // URL Route.
|
||||||
|
include: ['**/*.{js,jsx}'], // Extensions to include.
|
||||||
|
component: '@theme/Pages',
|
||||||
|
};
|
||||||
|
|
||||||
|
class DocusaurusPluginContentPages {
|
||||||
|
constructor(opts, context) {
|
||||||
|
this.options = {...DEFAULT_OPTIONS, ...opts};
|
||||||
|
this.context = context;
|
||||||
|
this.contentPath = path.resolve(this.context.siteDir, this.options.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return 'docusaurus-plugin-content-pages';
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadContents() {
|
||||||
|
const {include} = this.options;
|
||||||
|
const {env, siteConfig} = this.context;
|
||||||
|
const pagesDir = this.contentPath;
|
||||||
|
|
||||||
|
const {baseUrl} = siteConfig;
|
||||||
|
const pagesFiles = await globby(include, {
|
||||||
|
cwd: pagesDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata = {
|
||||||
|
permalink: pathName.replace(/^\//, `${baseUrl}${langTag}/`),
|
||||||
|
language: langTag,
|
||||||
|
source,
|
||||||
|
};
|
||||||
|
pagesMetadatas.push(metadata);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Default Language.
|
||||||
|
const metadata = {
|
||||||
|
permalink: pathName.replace(/^\//, baseUrl),
|
||||||
|
source,
|
||||||
|
};
|
||||||
|
pagesMetadatas.push(metadata);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return pagesMetadatas;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateRoutes({metadata, actions}) {
|
||||||
|
const {component} = this.options;
|
||||||
|
const {addRoute} = actions;
|
||||||
|
|
||||||
|
metadata.forEach(metadataItem => {
|
||||||
|
const {permalink, source} = metadataItem;
|
||||||
|
addRoute({
|
||||||
|
path: permalink,
|
||||||
|
component,
|
||||||
|
metadata: metadataItem,
|
||||||
|
modules: [source],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getPathsToWatch() {
|
||||||
|
// Not needed, all pages are loaded as modules and watched by webpack.
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DocusaurusPluginContentPages;
|
|
@ -18,4 +18,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,4 +18,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,4 +19,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,4 +19,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,4 +18,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
headerIcon: 'img/docusaurus.svg',
|
headerIcon: 'img/docusaurus.svg',
|
||||||
favicon: 'img/docusaurus.ico',
|
favicon: 'img/docusaurus.ico',
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'docusaurus-plugin-content-pages',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ module.exports = {
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^@lib/(.*)$': '<rootDir>/lib/$1',
|
'^@lib/(.*)$': '<rootDir>/lib/$1',
|
||||||
|
'^@test/(.*)$': '<rootDir>/test/$1',
|
||||||
},
|
},
|
||||||
testPathIgnorePatterns: ['/node_modules/', '__fixtures__', 'v1'],
|
testPathIgnorePatterns: ['/node_modules/', '__fixtures__', 'v1'],
|
||||||
transform: {
|
transform: {
|
||||||
|
|
|
@ -34,6 +34,11 @@ Object {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"organizationName": "endiliey",
|
"organizationName": "endiliey",
|
||||||
|
"plugins": Array [
|
||||||
|
Object {
|
||||||
|
"name": "docusaurus-plugin-content-pages",
|
||||||
|
},
|
||||||
|
],
|
||||||
"projectName": "hello",
|
"projectName": "hello",
|
||||||
"tagline": "Hello World",
|
"tagline": "Hello World",
|
||||||
"title": "Hello",
|
"title": "Hello",
|
||||||
|
|
|
@ -1,123 +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 loadPages from '@lib/load/pages';
|
|
||||||
import path from 'path';
|
|
||||||
import loadSetup from '../loadSetup';
|
|
||||||
|
|
||||||
describe('loadPages', () => {
|
|
||||||
test('simple website', async () => {
|
|
||||||
const {pagesDir, env, siteConfig} = await loadSetup('simple');
|
|
||||||
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
|
||||||
expect(pagesMetadatas).toEqual([
|
|
||||||
{
|
|
||||||
permalink: '/',
|
|
||||||
source: path.join(pagesDir, 'index.js'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
permalink: '/hello/world',
|
|
||||||
source: path.join(pagesDir, 'hello', 'world.js'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('versioned website', async () => {
|
|
||||||
const {pagesDir, env, siteConfig} = await loadSetup('versioned');
|
|
||||||
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
|
||||||
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'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('invalid pages', async () => {
|
|
||||||
const {env, siteConfig} = await loadSetup('simple');
|
|
||||||
const pagesDir = path.join(__dirname, '__fixtures__', 'nonExisting');
|
|
||||||
const pagesMetadatas = await loadPages({pagesDir, env, siteConfig});
|
|
||||||
expect(pagesMetadatas).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -5,13 +5,11 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import loadRoutes from '@lib/load/routes';
|
|
||||||
import loadSetup from '../loadSetup';
|
import loadSetup from '../loadSetup';
|
||||||
|
|
||||||
describe('loadRoutes', () => {
|
describe('loadRoutes', () => {
|
||||||
test('simple website', async () => {
|
test('simple website', async () => {
|
||||||
const props = await loadSetup('simple');
|
const {routesPaths} = await loadSetup('simple');
|
||||||
const {routesPaths} = await loadRoutes(props);
|
|
||||||
expect(routesPaths.length).toBeGreaterThan(0);
|
expect(routesPaths.length).toBeGreaterThan(0);
|
||||||
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
|
@ -26,8 +24,7 @@ Array [
|
||||||
});
|
});
|
||||||
|
|
||||||
test('versioned website', async () => {
|
test('versioned website', async () => {
|
||||||
const props = await loadSetup('versioned');
|
const {routesPaths} = await loadSetup('versioned');
|
||||||
const {routesPaths} = await loadRoutes(props);
|
|
||||||
expect(routesPaths.length).toBeGreaterThan(0);
|
expect(routesPaths.length).toBeGreaterThan(0);
|
||||||
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
|
@ -48,8 +45,7 @@ Array [
|
||||||
});
|
});
|
||||||
|
|
||||||
test('versioned & translated website', async () => {
|
test('versioned & translated website', async () => {
|
||||||
const props = await loadSetup('transversioned');
|
const {routesPaths} = await loadSetup('transversioned');
|
||||||
const {routesPaths} = await loadRoutes(props);
|
|
||||||
expect(routesPaths.length).toBeGreaterThan(0);
|
expect(routesPaths.length).toBeGreaterThan(0);
|
||||||
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
|
@ -83,8 +79,7 @@ Array [
|
||||||
});
|
});
|
||||||
|
|
||||||
test('translated website', async () => {
|
test('translated website', async () => {
|
||||||
const props = await loadSetup('translated');
|
const {routesPaths} = await loadSetup('translated');
|
||||||
const {routesPaths} = await loadRoutes(props);
|
|
||||||
expect(routesPaths.length).toBeGreaterThan(0);
|
expect(routesPaths.length).toBeGreaterThan(0);
|
||||||
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
expect(routesPaths.sort()).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue