mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-23 20:23:08 +00:00
[Beta] Don't rely on special MDX props (#4991)
This commit is contained in:
@@ -26,7 +26,6 @@
|
||||
"@docsearch/css": "3.0.0-alpha.41",
|
||||
"@docsearch/react": "3.0.0-alpha.41",
|
||||
"@headlessui/react": "^1.3.0",
|
||||
"@mdx-js/react": "^1.6.16",
|
||||
"body-scroll-lock": "^3.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.16.1",
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
// @ts-ignore
|
||||
import {MDXContext} from '@mdx-js/react';
|
||||
import {DocsPageFooter} from 'components/DocsFooter';
|
||||
import {MDXComponents} from 'components/MDX/MDXComponents';
|
||||
import {Seo} from 'components/Seo';
|
||||
@@ -45,11 +43,7 @@ export function MarkdownPage<
|
||||
/>
|
||||
)}
|
||||
<div className="px-5 sm:px-12">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<MDXContext.Provider value={MDXComponents}>
|
||||
{children}
|
||||
</MDXContext.Provider>
|
||||
</div>
|
||||
<div className="max-w-7xl mx-auto">{children}</div>
|
||||
<DocsPageFooter
|
||||
route={route}
|
||||
nextRoute={nextRoute}
|
||||
|
||||
@@ -37,8 +37,8 @@ const parseChallengeContents = (
|
||||
let challenge: Partial<ChallengeContents> = {};
|
||||
let content: React.ReactElement[] = [];
|
||||
React.Children.forEach(children, (child) => {
|
||||
const {props} = child;
|
||||
switch (props.mdxType) {
|
||||
const {props, type} = child;
|
||||
switch ((type as any).mdxName) {
|
||||
case 'Solution': {
|
||||
challenge.solution = child;
|
||||
challenge.content = content;
|
||||
|
||||
@@ -12,10 +12,10 @@ interface CodeDiagramProps {
|
||||
|
||||
export function CodeDiagram({children, flip = false}: CodeDiagramProps) {
|
||||
const illustration = React.Children.toArray(children).filter((child: any) => {
|
||||
return child.props?.mdxType === 'img';
|
||||
return child.type?.mdxName === 'img';
|
||||
});
|
||||
const content = React.Children.toArray(children).map((child: any) => {
|
||||
if (child.props?.mdxType === 'pre') {
|
||||
if (child.type?.mdxName === 'pre') {
|
||||
return (
|
||||
<CodeBlock
|
||||
{...child.props.children.props}
|
||||
@@ -23,7 +23,7 @@ export function CodeDiagram({children, flip = false}: CodeDiagramProps) {
|
||||
noMarkers={true}
|
||||
/>
|
||||
);
|
||||
} else if (child.props?.mdxType === 'img') {
|
||||
} else if (child.type?.mdxName === 'img') {
|
||||
return null;
|
||||
} else {
|
||||
return child;
|
||||
|
||||
@@ -71,6 +71,7 @@ export const H2 = ({className, ...props}: HeadingProps) => (
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export const H3 = ({className, ...props}: HeadingProps) => (
|
||||
<Heading
|
||||
as="h3"
|
||||
|
||||
@@ -18,7 +18,7 @@ function Link({
|
||||
'inline text-link dark:text-link-dark break-normal border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal';
|
||||
const modifiedChildren = React.Children.toArray(children).map(
|
||||
(child: any) => {
|
||||
if (child.props?.mdxType && child.props?.mdxType === 'inlineCode') {
|
||||
if (child.type?.mdxName && child.type?.mdxName === 'inlineCode') {
|
||||
return React.cloneElement(child, {
|
||||
isLink: true,
|
||||
});
|
||||
|
||||
@@ -325,3 +325,10 @@ export const MDXComponents = {
|
||||
Solution,
|
||||
CodeStep,
|
||||
};
|
||||
|
||||
for (let key in MDXComponents) {
|
||||
if (MDXComponents.hasOwnProperty(key)) {
|
||||
const MDXComponent: any = (MDXComponents as any)[key];
|
||||
MDXComponent.mdxName = key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ interface PackageImportProps {
|
||||
|
||||
export function PackageImport({children}: PackageImportProps) {
|
||||
const terminal = React.Children.toArray(children).filter((child: any) => {
|
||||
return child.props?.mdxType !== 'pre';
|
||||
return child.type?.mdxName !== 'pre';
|
||||
});
|
||||
const code = React.Children.toArray(children).map((child: any, i: number) => {
|
||||
if (child.props?.mdxType === 'pre') {
|
||||
if (child.type?.mdxName === 'pre') {
|
||||
return (
|
||||
<CodeBlock
|
||||
{...child.props.children.props}
|
||||
|
||||
@@ -7,7 +7,7 @@ import type {SandpackFile} from '@codesandbox/sandpack-react';
|
||||
export const createFileMap = (codeSnippets: any) => {
|
||||
return codeSnippets.reduce(
|
||||
(result: Record<string, SandpackFile>, codeSnippet: React.ReactElement) => {
|
||||
if (codeSnippet.props.mdxType !== 'pre') {
|
||||
if ((codeSnippet.type as any).mdxName !== 'pre') {
|
||||
return result;
|
||||
}
|
||||
const {props} = codeSnippet.props.children;
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*/
|
||||
|
||||
import {createElement, Children, useMemo} from 'react';
|
||||
import {createElement, Children, Fragment, useMemo} from 'react';
|
||||
import {MDXComponents} from 'components/MDX/MDXComponents';
|
||||
import {MarkdownPage} from 'components/Layout/MarkdownPage';
|
||||
import {Page} from 'components/Layout/Page';
|
||||
import {mdx} from '@mdx-js/react';
|
||||
import {prepareMDX} from '../utils/prepareMDX';
|
||||
|
||||
export default function Layout({content, meta}) {
|
||||
const decoded = useMemo(() => JSON.parse(content, reviveMDX), [content]);
|
||||
const decoded = useMemo(
|
||||
() => JSON.parse(content, reviveNodeOnClient),
|
||||
[content]
|
||||
);
|
||||
const {toc, children} = useMemo(
|
||||
() => prepareMDX(decoded.props.children),
|
||||
[decoded]
|
||||
@@ -24,20 +26,48 @@ export default function Layout({content, meta}) {
|
||||
);
|
||||
}
|
||||
|
||||
// Create a React tree from server JSON.
|
||||
function reviveMDX(key, val) {
|
||||
if (val && val.$m) {
|
||||
// This is an MDX node we need to revive.
|
||||
let args = val.$m;
|
||||
if (args[0] == null) {
|
||||
// First argument to createElement() is a type.
|
||||
// If it didn't serialize, this is a custom MDX component.
|
||||
args[0] = MDXComponents[args[1].mdxType];
|
||||
if (args[0] == null) {
|
||||
throw Error('Unknown type: ' + args[1].mdxType);
|
||||
}
|
||||
// Deserialize a client React tree from JSON.
|
||||
function reviveNodeOnClient(key, val) {
|
||||
if (Array.isArray(val) && val[0] == '$r') {
|
||||
// Assume it's a React element.
|
||||
let type = val[1];
|
||||
let key = val[2];
|
||||
let props = val[3];
|
||||
if (type === 'wrapper') {
|
||||
type = Fragment;
|
||||
props = {children: props.children};
|
||||
}
|
||||
return mdx.apply(null, args);
|
||||
if (MDXComponents[type]) {
|
||||
type = MDXComponents[type];
|
||||
}
|
||||
if (!type) {
|
||||
console.error('Unknown type: ' + type);
|
||||
type = Fragment;
|
||||
}
|
||||
return {
|
||||
$$typeof: Symbol.for('react.element'),
|
||||
type: type,
|
||||
key: key,
|
||||
ref: null,
|
||||
props: props,
|
||||
_owner: null,
|
||||
};
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize a server React tree node to JSON.
|
||||
function stringifyNodeOnServer(key, val) {
|
||||
if (val != null && val.$$typeof === Symbol.for('react.element')) {
|
||||
// Remove fake MDX props.
|
||||
const {mdxType, originalType, parentName, ...cleanProps} = val.props;
|
||||
return [
|
||||
'$r',
|
||||
typeof val.type === 'string' ? val.type : mdxType,
|
||||
val.key,
|
||||
cleanProps,
|
||||
];
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
@@ -72,14 +102,11 @@ export async function getStaticProps(context) {
|
||||
// Run it to get JSON for render output
|
||||
const run = new Function('exports', 'mdx', js);
|
||||
let outputExports = {};
|
||||
function createJSONNode(...args) {
|
||||
return {$m: args}; // Marker to turn this into createElement on the client
|
||||
}
|
||||
run(outputExports, createJSONNode);
|
||||
const json = outputExports.default({});
|
||||
run(outputExports, createElement);
|
||||
const reactTree = outputExports.default({});
|
||||
return {
|
||||
props: {
|
||||
content: JSON.stringify(json),
|
||||
content: JSON.stringify(reactTree, stringifyNodeOnServer),
|
||||
meta,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ function wrapChildrenInMaxWidthContainers(children) {
|
||||
wrapQueue.push(child);
|
||||
return;
|
||||
}
|
||||
if (fullWidthTypes.includes(child.props.mdxType)) {
|
||||
if (fullWidthTypes.includes(child.type.mdxName)) {
|
||||
flushWrapper(key);
|
||||
finalChildren.push(child);
|
||||
} else {
|
||||
@@ -59,22 +59,22 @@ function wrapChildrenInMaxWidthContainers(children) {
|
||||
function getTableOfContents(children) {
|
||||
const anchors = Children.toArray(children)
|
||||
.filter((child) => {
|
||||
if (child.props?.mdxType) {
|
||||
if (child.type?.mdxName) {
|
||||
return ['h1', 'h2', 'h3', 'Challenges', 'Recap'].includes(
|
||||
child.props.mdxType
|
||||
child.type.mdxName
|
||||
);
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map((child) => {
|
||||
if (child.props.mdxType === 'Challenges') {
|
||||
if (child.type.mdxName === 'Challenges') {
|
||||
return {
|
||||
url: '#challenges',
|
||||
depth: 0,
|
||||
text: 'Challenges',
|
||||
};
|
||||
}
|
||||
if (child.props.mdxType === 'Recap') {
|
||||
if (child.type.mdxName === 'Recap') {
|
||||
return {
|
||||
url: '#recap',
|
||||
depth: 0,
|
||||
@@ -84,8 +84,8 @@ function getTableOfContents(children) {
|
||||
return {
|
||||
url: '#' + child.props.id,
|
||||
depth:
|
||||
(child.props?.mdxType &&
|
||||
parseInt(child.props.mdxType.replace('h', ''), 0)) ??
|
||||
(child.type?.mdxName &&
|
||||
parseInt(child.type.mdxName.replace('h', ''), 0)) ??
|
||||
0,
|
||||
text: child.props.children,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user