You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.4 KiB
99 lines
2.4 KiB
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*/
|
|
|
|
import {Children} from 'react';
|
|
|
|
// TODO: This logic could be in MDX plugins instead.
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
export const PREPARE_MDX_CACHE_BREAKER = 2;
|
|
// !!! IMPORTANT !!! Bump this if you change any logic.
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
export function prepareMDX(rawChildren) {
|
|
const toc = getTableOfContents(rawChildren);
|
|
const children = wrapChildrenInMaxWidthContainers(rawChildren);
|
|
return {toc, children};
|
|
}
|
|
|
|
function wrapChildrenInMaxWidthContainers(children) {
|
|
// Auto-wrap everything except a few types into
|
|
// <MaxWidth> wrappers. Keep reusing the same
|
|
// wrapper as long as we can until we meet
|
|
// a full-width section which interrupts it.
|
|
let fullWidthTypes = [
|
|
'Sandpack',
|
|
'FullWidth',
|
|
'Illustration',
|
|
'IllustrationBlock',
|
|
'Challenges',
|
|
'Recipes',
|
|
];
|
|
let wrapQueue = [];
|
|
let finalChildren = [];
|
|
function flushWrapper(key) {
|
|
if (wrapQueue.length > 0) {
|
|
const Wrapper = 'MaxWidth';
|
|
finalChildren.push(<Wrapper key={key}>{wrapQueue}</Wrapper>);
|
|
wrapQueue = [];
|
|
}
|
|
}
|
|
function handleChild(child, key) {
|
|
if (child == null) {
|
|
return;
|
|
}
|
|
if (typeof child !== 'object') {
|
|
wrapQueue.push(child);
|
|
return;
|
|
}
|
|
if (fullWidthTypes.includes(child.type)) {
|
|
flushWrapper(key);
|
|
finalChildren.push(child);
|
|
} else {
|
|
wrapQueue.push(child);
|
|
}
|
|
}
|
|
Children.forEach(children, handleChild);
|
|
flushWrapper('last');
|
|
return finalChildren;
|
|
}
|
|
|
|
function getTableOfContents(children) {
|
|
const anchors = Children.toArray(children)
|
|
.filter((child) => {
|
|
if (child.type) {
|
|
return ['h1', 'h2', 'h3', 'Challenges', 'Recap'].includes(child.type);
|
|
}
|
|
return false;
|
|
})
|
|
.map((child) => {
|
|
if (child.type === 'Challenges') {
|
|
return {
|
|
url: '#challenges',
|
|
depth: 2,
|
|
text: 'Challenges',
|
|
};
|
|
}
|
|
if (child.type === 'Recap') {
|
|
return {
|
|
url: '#recap',
|
|
depth: 2,
|
|
text: 'Recap',
|
|
};
|
|
}
|
|
return {
|
|
url: '#' + child.props.id,
|
|
depth: (child.type && parseInt(child.type.replace('h', ''), 0)) ?? 0,
|
|
text: child.props.children,
|
|
};
|
|
});
|
|
if (anchors.length > 0) {
|
|
anchors.unshift({
|
|
url: '#',
|
|
text: 'Overview',
|
|
depth: 2,
|
|
});
|
|
}
|
|
return anchors;
|
|
}
|
|
|