mirror of
https://github.com/bendtherules/react-to-markdown.git
synced 2026-08-18 13:53:11 +00:00
117 lines
3.3 KiB
TypeScript
117 lines
3.3 KiB
TypeScript
import { root, text } from 'mdast-builder';
|
|
import { Children as ReactChildren, Fragment } from 'react';
|
|
import * as stringify from 'remark-stringify';
|
|
import * as unified from 'unified';
|
|
// tslint:disable-next-line: no-implicit-dependencies
|
|
import { Parent as MDASTParent } from 'unist';
|
|
|
|
import {
|
|
isClassComponent,
|
|
isFunctionalComponent,
|
|
ReactElementSubsetWithPrimitive,
|
|
} from './helpers';
|
|
|
|
import handleTag from './tagHandler';
|
|
|
|
function render(
|
|
node: ReactElementSubsetWithPrimitive,
|
|
parentASTNode?: MDASTParent
|
|
): string | null {
|
|
let parentASTNodeMod: MDASTParent;
|
|
if (parentASTNode === undefined) {
|
|
parentASTNodeMod = root([]);
|
|
} else {
|
|
parentASTNodeMod = parentASTNode;
|
|
}
|
|
let nextParentASTNode = parentASTNodeMod;
|
|
|
|
if (node === null || node === undefined) {
|
|
// Handle (skip) null and undefined nodes
|
|
} else if (typeof node === 'string' || typeof node === 'number') {
|
|
// Handle (render) string and number nodes as string in markdown
|
|
|
|
const currASTNode = text(node.toString());
|
|
parentASTNodeMod.children.push(currASTNode);
|
|
} else if (Array.isArray(node)) {
|
|
// Handle (render) Fragment nodes or arrays
|
|
|
|
node.forEach(fragmentEle => render(fragmentEle, parentASTNodeMod));
|
|
} else if (node.type === Fragment) {
|
|
const childrenArray = ReactChildren.toArray(
|
|
node.props.children
|
|
) as ReactElementSubsetWithPrimitive[];
|
|
|
|
// Render processed array of children
|
|
render(childrenArray, parentASTNodeMod);
|
|
} else {
|
|
const { props, type: elementType } = node;
|
|
let processChildren = true;
|
|
|
|
// Handle nested function or class components
|
|
{
|
|
if (isFunctionalComponent(elementType)) {
|
|
const renderOutputRaw = elementType.call(null, props);
|
|
const renderOutput = ReactChildren.toArray(
|
|
renderOutputRaw
|
|
) as ReactElementSubsetWithPrimitive[];
|
|
|
|
// Render processed array of children
|
|
render(renderOutput, parentASTNodeMod);
|
|
}
|
|
|
|
if (isClassComponent(elementType)) {
|
|
const elementInstance = new elementType(props);
|
|
const renderOutputRaw = elementInstance.render();
|
|
const renderOutput = ReactChildren.toArray(
|
|
renderOutputRaw
|
|
) as ReactElementSubsetWithPrimitive[];
|
|
|
|
// Render processed array of children
|
|
render(renderOutput, parentASTNodeMod);
|
|
}
|
|
}
|
|
|
|
{
|
|
// Handle intrinsic types of element like div, h1
|
|
const newParentASTNode = handleTag(node, parentASTNodeMod);
|
|
if (newParentASTNode === undefined) {
|
|
processChildren = false;
|
|
} else {
|
|
processChildren = true;
|
|
nextParentASTNode = newParentASTNode;
|
|
}
|
|
}
|
|
|
|
// Handle children
|
|
if (processChildren) {
|
|
const { children } = props;
|
|
|
|
// Render processed array of children
|
|
const renderOutput = ReactChildren.toArray(
|
|
children
|
|
) as ReactElementSubsetWithPrimitive[];
|
|
|
|
render(renderOutput, nextParentASTNode);
|
|
}
|
|
}
|
|
|
|
// Return stuff
|
|
{
|
|
// For root call, return string
|
|
if (parentASTNode === undefined && parentASTNodeMod.children.length > 0) {
|
|
const processor = unified().use(stringify, {
|
|
bullet: '-',
|
|
fence: '`',
|
|
fences: true,
|
|
incrementListMarker: true,
|
|
});
|
|
const output = processor.stringify(parentASTNodeMod);
|
|
|
|
return output;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export { render };
|