renderer - Handle children and nested jsx, render to markdown

This commit is contained in:
2019-12-15 16:33:56 +05:30
parent b867ee52e4
commit eef2069e09
+83 -45
View File
@@ -1,59 +1,97 @@
import { root, text } from "mdast-builder";
import { Children as ReactChildren } from "react"; import { Children as ReactChildren } from "react";
import * as stringify from "remark-stringify";
import * as unified from "unified";
import { Parent as MDASTParent } from "unist";
import { import {
ReactElementSubset, isClassComponent,
ReactElementSubsetWithPrimitive,
isFunctionalComponent, isFunctionalComponent,
isClassComponent ReactElementSubsetWithPrimitive
} from "./helpers"; } from "./helpers";
function render( function render(
node: ReactElementSubsetWithPrimitive, node: ReactElementSubsetWithPrimitive,
parentNode?: ReactElementSubset parentASTNode?: MDASTParent
) { ): string | null {
// Skip null and undefined nodes let parentASTNodeMod: MDASTParent;
if (parentASTNode === undefined) {
parentASTNodeMod = root([]);
} else {
parentASTNodeMod = parentASTNode;
}
if (node === null || node === undefined) { if (node === null || node === undefined) {
return; // 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 {
const { props, type: elementType } = node;
// 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
{
}
{
// Handle children
const { children } = props;
// Render processed array of children
const renderOutput = ReactChildren.toArray(
children
) as ReactElementSubsetWithPrimitive[];
render(renderOutput, parentASTNodeMod);
}
} }
// Render string and number nodes // Return stuff
if (typeof node === "string" || typeof node === "number") {
return;
}
// Render Fragment nodes
if (Array.isArray(node)) {
node.forEach(fragmentEle => render(fragmentEle));
return;
}
const { props, type: elementType } = node;
const { children } = props;
if (isFunctionalComponent(elementType)) {
const renderOutput = elementType.call(
null,
props
) as ReactElementSubsetWithPrimitive;
render(renderOutput);
return;
}
if (isClassComponent(elementType)) {
const elementInstance = new elementType(props);
const renderOutputRaw = elementInstance.render();
const renderOutput = ReactChildren.toArray(
renderOutputRaw
) as ReactElementSubsetWithPrimitive[];
// Render array of children, just like fragments
render(renderOutput);
return;
}
// Handle intrinsic types of element like div, h1
{ {
// For root call, return string
if (parentASTNode === undefined && parentASTNodeMod.children.length > 0) {
const processor = unified().use(stringify, {
bullet: "-",
fence: "`",
fences: true,
incrementListMarker: false
});
const output = processor.stringify(parentASTNodeMod);
return output;
}
return null;
} }
} }