mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-03 11:22:30 +02:00
feat(v2): debug pages + debug layout + ability to debug content (#3229)
* improve debug plugin: - add multiple debug pages + debug layout - ability to debug plugin contentLoaded data * add missing dependency * fix broken test * improve content rendering a bit * create basic DebugJsonView * fix ReactJson SSR issues
This commit is contained in:
parent
be210a1bc4
commit
fe281a8ebe
30 changed files with 511 additions and 110 deletions
|
@ -6,13 +6,20 @@
|
|||
*/
|
||||
|
||||
import {LoadContext, Plugin} from '@docusaurus/types';
|
||||
import {normalizeUrl} from '@docusaurus/utils';
|
||||
|
||||
import {docuHash, normalizeUrl} from '@docusaurus/utils';
|
||||
import path from 'path';
|
||||
|
||||
export default function pluginContentPages({
|
||||
siteConfig: {baseUrl},
|
||||
generatedFilesDir,
|
||||
}: LoadContext): Plugin<void> {
|
||||
const pluginDataDirRoot = path.join(
|
||||
generatedFilesDir,
|
||||
'docusaurus-plugin-debug',
|
||||
);
|
||||
const aliasedSource = (source: string) =>
|
||||
`~debug/${path.relative(pluginDataDirRoot, source)}`;
|
||||
|
||||
return {
|
||||
name: 'docusaurus-plugin-debug',
|
||||
|
||||
|
@ -20,12 +27,63 @@ export default function pluginContentPages({
|
|||
return path.resolve(__dirname, '../src/theme');
|
||||
},
|
||||
|
||||
contentLoaded({actions: {addRoute}}) {
|
||||
async contentLoaded({actions: {createData, addRoute}, allContent}) {
|
||||
const allContentPath = await createData(
|
||||
// Note that this created data path must be in sync with
|
||||
// metadataPath provided to mdx-loader.
|
||||
`${docuHash('docusaurus-debug-allContent')}.json`,
|
||||
JSON.stringify(allContent, null, 2),
|
||||
);
|
||||
|
||||
// Home is config (duplicate for now)
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug']),
|
||||
component: '@theme/Debug',
|
||||
component: '@theme/DebugConfig',
|
||||
exact: true,
|
||||
});
|
||||
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug/config']),
|
||||
component: '@theme/DebugConfig',
|
||||
exact: true,
|
||||
});
|
||||
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug/metadata']),
|
||||
component: '@theme/DebugMetadata',
|
||||
exact: true,
|
||||
});
|
||||
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug/registry']),
|
||||
component: '@theme/DebugRegistry',
|
||||
exact: true,
|
||||
});
|
||||
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug/routes']),
|
||||
component: '@theme/DebugRoutes',
|
||||
exact: true,
|
||||
});
|
||||
|
||||
addRoute({
|
||||
path: normalizeUrl([baseUrl, '__docusaurus/debug/content']),
|
||||
component: '@theme/DebugContent',
|
||||
exact: true,
|
||||
modules: {
|
||||
allContent: aliasedSource(allContentPath),
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
configureWebpack() {
|
||||
return {
|
||||
resolve: {
|
||||
alias: {
|
||||
'~debug': pluginDataDirRoot,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
import registry from '@generated/registry';
|
||||
import routes from '@generated/routes';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
function Debug() {
|
||||
const {siteMetadata} = useDocusaurusContext();
|
||||
return (
|
||||
<Layout permalink="__docusaurus/debug" title="Debug">
|
||||
<main className={styles.Container}>
|
||||
<section className={styles.Section}>
|
||||
<h2>Site Metadata</h2>
|
||||
<div>Docusaurus Version: {siteMetadata.docusaurusVersion}</div>
|
||||
<div>
|
||||
Site Version: {siteMetadata.siteVersion || 'No version specified'}
|
||||
</div>
|
||||
<h3>Plugins and themes:</h3>
|
||||
<ul>
|
||||
{Object.entries(siteMetadata.pluginVersions).map(
|
||||
([name, versionInformation]) => (
|
||||
<li key={name}>
|
||||
<div>Name: {name}</div>
|
||||
<div>Type: {versionInformation.type}</div>
|
||||
{versionInformation.version && (
|
||||
<div>Version: {versionInformation.version}</div>
|
||||
)}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
</section>
|
||||
<section className={styles.Section}>
|
||||
<h2>Registry</h2>
|
||||
<ul>
|
||||
{Object.values(registry).map(([, aliasedPath, resolved]) => (
|
||||
<li key={aliasedPath}>
|
||||
<div>Aliased Path: {aliasedPath}</div>
|
||||
<div>Resolved Path: {resolved}</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
<section className={styles.Section}>
|
||||
<h2>Routes</h2>
|
||||
<ul>
|
||||
{routes.map(({path, exact}) => (
|
||||
<li key={path}>
|
||||
<div>Route: {path}</div>
|
||||
<div>Is exact: {String(Boolean(exact))}</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default Debug;
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
|
||||
import DebugLayout from '../DebugLayout';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
function DebugMetadata() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<DebugLayout>
|
||||
<h2>Site config</h2>
|
||||
<div>{JSON.stringify(siteConfig, null, 2)}</div>
|
||||
</DebugLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugMetadata;
|
|
@ -5,13 +5,3 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.Container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.Section {
|
||||
width: 500px;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import DebugLayout from '../DebugLayout';
|
||||
import DebugJsonView from '../DebugJsonView';
|
||||
|
||||
const PluginInstanceContent = ({pluginId, pluginInstanceContent}) => (
|
||||
<section style={{marginBottom: 30}}>
|
||||
<h4>{`>> ${pluginId}`}</h4>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
padding: 10,
|
||||
border: 'thin cyan solid',
|
||||
borderRadius: 5,
|
||||
backgroundColor: 'lightgrey',
|
||||
}}>
|
||||
<DebugJsonView src={pluginInstanceContent} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
const PluginContent = ({pluginName, pluginContent}) => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
return (
|
||||
<section style={{marginBottom: 60}}>
|
||||
<h3 onClick={() => setVisible((v) => !v)} style={{cursor: 'pointer'}}>
|
||||
{pluginName}
|
||||
</h3>
|
||||
{visible && (
|
||||
<div>
|
||||
{Object.entries(pluginContent)
|
||||
// filter plugin instances with no content
|
||||
.filter(
|
||||
([_pluginId, pluginInstanceContent]) => !!pluginInstanceContent,
|
||||
)
|
||||
.map(([pluginId, pluginInstanceContent]) => {
|
||||
return (
|
||||
<PluginInstanceContent
|
||||
key={pluginId}
|
||||
pluginId={pluginId}
|
||||
pluginInstanceContent={pluginInstanceContent}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
function DebugContent({allContent}) {
|
||||
return (
|
||||
<DebugLayout>
|
||||
<h2>Plugin content</h2>
|
||||
<div>
|
||||
{Object.entries(allContent)
|
||||
// filter plugins with no content
|
||||
.filter(([_pluginName, pluginContent]) =>
|
||||
Object.values(pluginContent).some(
|
||||
(instanceContent) => !!instanceContent,
|
||||
),
|
||||
)
|
||||
.map(([pluginName, pluginContent]) => {
|
||||
return (
|
||||
<PluginContent
|
||||
key={pluginName}
|
||||
pluginName={pluginName}
|
||||
pluginContent={pluginContent}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</DebugLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugContent;
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
|
||||
import BrowserOnly from '@docusaurus/BrowserOnly';
|
||||
|
||||
// avoids "react-json-view" to display "root"
|
||||
const RootName = false;
|
||||
|
||||
// Seems ReactJson does not work with SSR
|
||||
// https://github.com/mac-s-g/react-json-view/issues/121
|
||||
const BrowserOnlyReactJson = (props) => {
|
||||
return (
|
||||
<BrowserOnly>
|
||||
{() => {
|
||||
const ReactJson = require('react-json-view').default;
|
||||
return <ReactJson {...props} />;
|
||||
}}
|
||||
</BrowserOnly>
|
||||
);
|
||||
};
|
||||
|
||||
function DebugJsonView({src}) {
|
||||
return (
|
||||
<BrowserOnlyReactJson
|
||||
src={src}
|
||||
name={RootName}
|
||||
shouldCollapse={(field) => {
|
||||
// By default, we collapse the json for performance reasons
|
||||
// See https://github.com/mac-s-g/react-json-view/issues/235
|
||||
// only the "root" is not collapsed
|
||||
return field.name !== RootName;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugJsonView;
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
import Link from '@docusaurus/Link';
|
||||
// import styles from './styles.module.css';
|
||||
|
||||
const DebugNavLink = ({to, children}) => (
|
||||
<Link
|
||||
style={{margin: 10}}
|
||||
className="button button--primary"
|
||||
isNavLink
|
||||
activeClassName="button--active"
|
||||
to={to}
|
||||
exact>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
|
||||
function DebugLayout({children}) {
|
||||
return (
|
||||
<div>
|
||||
<nav style={{width: '100%', padding: 10, border: 'solid'}}>
|
||||
<DebugNavLink to="/__docusaurus/debug">Config</DebugNavLink>
|
||||
<DebugNavLink to="/__docusaurus/debug/metadata">Metadata</DebugNavLink>
|
||||
<DebugNavLink to="/__docusaurus/debug/registry">Registry</DebugNavLink>
|
||||
<DebugNavLink to="/__docusaurus/debug/routes">Routes</DebugNavLink>
|
||||
<DebugNavLink to="/__docusaurus/debug/content">Content</DebugNavLink>
|
||||
</nav>
|
||||
<main style={{padding: 20}}>{children}</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugLayout;
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
|
||||
import DebugLayout from '../DebugLayout';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
function DebugMetadata() {
|
||||
const {siteMetadata} = useDocusaurusContext();
|
||||
return (
|
||||
<DebugLayout>
|
||||
<h2>Site Metadata</h2>
|
||||
<div>Docusaurus Version: {siteMetadata.docusaurusVersion}</div>
|
||||
<div>
|
||||
Site Version: {siteMetadata.siteVersion || 'No version specified'}
|
||||
</div>
|
||||
<h3>Plugins and themes:</h3>
|
||||
<ul>
|
||||
{Object.entries(siteMetadata.pluginVersions).map(
|
||||
([name, versionInformation]) => (
|
||||
<li key={name}>
|
||||
<div>Name: {name}</div>
|
||||
<div>Type: {versionInformation.type}</div>
|
||||
{versionInformation.version && (
|
||||
<div>Version: {versionInformation.version}</div>
|
||||
)}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
</DebugLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugMetadata;
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
|
||||
import DebugLayout from '../DebugLayout';
|
||||
import registry from '@generated/registry';
|
||||
|
||||
function DebugRegistry() {
|
||||
return (
|
||||
<DebugLayout>
|
||||
{' '}
|
||||
<h2>Registry</h2>
|
||||
<ul>
|
||||
{Object.values(registry).map(([, aliasedPath, resolved]) => (
|
||||
<li key={aliasedPath}>
|
||||
<div>Aliased Path: {aliasedPath}</div>
|
||||
<div>Resolved Path: {resolved}</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</DebugLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugRegistry;
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* 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';
|
||||
|
||||
import DebugLayout from '../DebugLayout';
|
||||
import routes from '@generated/routes';
|
||||
|
||||
function DebugRoutes() {
|
||||
return (
|
||||
<DebugLayout>
|
||||
<h2>Routes</h2>
|
||||
<ul>
|
||||
{routes.map(({path, exact}) => (
|
||||
<li key={path}>
|
||||
<div>Route: {path}</div>
|
||||
<div>Is exact: {String(Boolean(exact))}</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</DebugLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default DebugRoutes;
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue