Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const nodeContainerTypes = new Map([
['delete', 'block'],
[BLOCKS.HEADING_1, 'block'],
[BLOCKS.HEADING_2, 'block'],
[BLOCKS.HEADING_3, 'block'],
[BLOCKS.HEADING_4, 'block'],
[BLOCKS.HEADING_5, 'block'],
[BLOCKS.HEADING_6, 'block'],
[BLOCKS.LIST_ITEM, 'block'],
[BLOCKS.UL_LIST, 'block'],
[BLOCKS.OL_LIST, 'block'],
[BLOCKS.QUOTE, 'block'],
[BLOCKS.HR, 'block'],
[BLOCKS.PARAGRAPH, 'block'],
[INLINES.HYPERLINK, 'inline'],
['text', 'text'],
['emphasis', 'text'],
['strong', 'text'],
['inlineCode', 'text'],
]);
const isBlock = (nodeType: string) => {
return nodeContainerTypes.get(nodeType) === 'block';
};
const isText = (nodeType: string) => {
return nodeContainerTypes.get(nodeType) === 'text';
};
const isInline = (nodeType: string) => {
return nodeContainerTypes.get(nodeType) === 'inline';
const buildHyperlink = async (
node: MarkdownLinkNode,
fallback: FallbackResolver,
appliedMarksTypes: string[],
): Promise => {
const content = (await mdToRichTextNodes(node.children, fallback, appliedMarksTypes)) as Text[];
const hyperlink: Hyperlink = {
nodeType: INLINES.HYPERLINK,
data: { uri: node.url },
content,
};
return [hyperlink];
};
nodeType: 'text'
};
export const hyperlink = {
data: {
uri: 'https://acme.com'
},
content: [
{
data: {},
marks: [],
value: 'This is a hyperlink.',
nodeType: 'text'
}
],
nodeType: INLINES.HYPERLINK
};
export const boldAndItalic = {
data: {},
marks: [
{
type: MARKS.BOLD
},
{
type: MARKS.ITALIC
}
],
value: 'This is bold and italic text.',
nodeType: 'text'
};
[BLOCKS.HEADING_1]: (node, children) => <h1>{children}</h1>,
[BLOCKS.HEADING_2]: (node, children) => <h2>{children}</h2>,
[BLOCKS.HEADING_3]: (node, children) => <h3>{children}</h3>,
[BLOCKS.HEADING_4]: (node, children) => <h4>{children}</h4>,
[BLOCKS.HEADING_5]: (node, children) => <h5>{children}</h5>,
[BLOCKS.HEADING_6]: (node, children) => <h6>{children}</h6>,
[BLOCKS.EMBEDDED_ENTRY]: (node, children) => <div>{children}</div>,
[BLOCKS.UL_LIST]: (node, children) => <ul>{children}</ul>,
[BLOCKS.OL_LIST]: (node, children) => <ol>{children}</ol>,
[BLOCKS.LIST_ITEM]: (node, children) => <li>{children}</li>,
[BLOCKS.QUOTE]: (node, children) => <blockquote>{children}</blockquote>,
[BLOCKS.HR]: () => <hr>,
[INLINES.ASSET_HYPERLINK]: node => defaultInline(INLINES.ASSET_HYPERLINK, node as Inline),
[INLINES.ENTRY_HYPERLINK]: node => defaultInline(INLINES.ENTRY_HYPERLINK, node as Inline),
[INLINES.EMBEDDED_ENTRY]: node => defaultInline(INLINES.EMBEDDED_ENTRY, node as Inline),
[INLINES.HYPERLINK]: (node, children) => <a href="{node.data.uri}">{children}</a>,
};
const defaultMarkRenderers: RenderMark = {
[MARKS.BOLD]: text => <b>{text}</b>,
[MARKS.ITALIC]: text => <i>{text}</i>,
[MARKS.UNDERLINE]: text => <u>{text}</u>,
[MARKS.CODE]: text => <code>{text}</code>,
};
function defaultInline(type: string, node: Inline): ReactNode {
return (
<span>
type: {node.nodeType} id: {node.data.target.sys.id}
</span>
);
}
INLINES,
Hyperlink,
Text,
Inline,
} from '@contentful/rich-text-types';
import { MarkdownNode, MarkdownLinkNode, MarkdownTree } from './types';
const markdownNodeTypes = new Map([
['paragraph', BLOCKS.PARAGRAPH],
['heading', 'heading'],
['text', 'text'],
['emphasis', 'text'],
['strong', 'text'],
['delete', 'text'],
['inlineCode', 'text'],
['link', INLINES.HYPERLINK],
['thematicBreak', BLOCKS.HR],
['blockquote', BLOCKS.QUOTE],
['list', 'list'],
['listItem', BLOCKS.LIST_ITEM],
]);
const nodeTypeFor = (node: MarkdownNode) => {
const nodeType = markdownNodeTypes.get(node.type);
switch (nodeType) {
case 'heading':
return `${nodeType}-${node.depth}`;
case 'list':
return `${node.ordered ? 'ordered' : 'unordered'}-list`;
default:
return nodeType;
[BLOCKS.HEADING_1]: (node, next) => `<h1>${next(node.content)}</h1>`,
[BLOCKS.HEADING_2]: (node, next) => `<h2>${next(node.content)}</h2>`,
[BLOCKS.HEADING_3]: (node, next) => `<h3>${next(node.content)}</h3>`,
[BLOCKS.HEADING_4]: (node, next) => `<h4>${next(node.content)}</h4>`,
[BLOCKS.HEADING_5]: (node, next) => `<h5>${next(node.content)}</h5>`,
[BLOCKS.HEADING_6]: (node, next) => `<h6>${next(node.content)}</h6>`,
[BLOCKS.EMBEDDED_ENTRY]: (node, next) => `<div>${next(node.content)}</div>`,
[BLOCKS.UL_LIST]: (node, next) => `<ul>${next(node.content)}</ul>`,
[BLOCKS.OL_LIST]: (node, next) => `<ol>${next(node.content)}</ol>`,
[BLOCKS.LIST_ITEM]: (node, next) => `<li>${next(node.content)}</li>`,
[BLOCKS.QUOTE]: (node, next) => `<blockquote>${next(node.content)}</blockquote>`,
[BLOCKS.HR]: () => '<hr>',
[INLINES.ASSET_HYPERLINK]: node => defaultInline(INLINES.ASSET_HYPERLINK, node as Inline),
[INLINES.ENTRY_HYPERLINK]: node => defaultInline(INLINES.ENTRY_HYPERLINK, node as Inline),
[INLINES.EMBEDDED_ENTRY]: node => defaultInline(INLINES.EMBEDDED_ENTRY, node as Inline),
[INLINES.HYPERLINK]: (node, next) => `<a href="${node.data.uri}">${next(node.content)}</a>`,
};
const defaultMarkRenderers: RenderMark = {
[MARKS.BOLD]: text => `<b>${text}</b>`,
[MARKS.ITALIC]: text => `<i>${text}</i>`,
[MARKS.UNDERLINE]: text => `<u>${text}</u>`,
[MARKS.CODE]: text => `<code>${text}</code>`,
};
const defaultInline = (type: string, node: Inline) =>
`<span>type: ${type} id: ${node.data.target.sys.id}</span>`;
export type CommonNode = Text | Block | Inline;
export interface Next {
(nodes: CommonNode[]): string;
};
const tagMap = {
[BLOCKS.HEADING_1]: 'h1',
[BLOCKS.HEADING_2]: 'h2',
[BLOCKS.HEADING_3]: 'h3',
[BLOCKS.HEADING_4]: 'h4',
[BLOCKS.HEADING_5]: 'h5',
[BLOCKS.HEADING_6]: 'h6',
[BLOCKS.PARAGRAPH]: 'p',
[BLOCKS.UL_LIST]: 'ul',
[BLOCKS.OL_LIST]: 'ol',
[BLOCKS.LIST_ITEM]: 'li',
[BLOCKS.QUOTE]: 'blockquote',
[BLOCKS.HR]: 'hr',
[INLINES.HYPERLINK]: 'a',
[MARKS.BOLD]: 'strong',
[MARKS.ITALIC]: 'em',
[MARKS.UNDERLINE]: 'u',
[MARKS.CODE]: 'code'
};
const entryMap = {
[BLOCKS.EMBEDDED_ENTRY]: true,
[INLINES.ENTRY_HYPERLINK]: true,
[INLINES.EMBEDDED_ENTRY]: true
};
const assetMap = {
[BLOCKS.EMBEDDED_ASSET]: true,
[INLINES.ASSET_HYPERLINK]: true
};
[BLOCKS.HEADING_1]: (node, key, next) => <h1>{next(node.content, key, next)}</h1>,
[BLOCKS.HEADING_2]: (node, key, next) => <h2>{next(node.content, key, next)}</h2>,
[BLOCKS.HEADING_3]: (node, key, next) => <h3>{next(node.content, key, next)}</h3>,
[BLOCKS.HEADING_4]: (node, key, next) => <h4>{next(node.content, key, next)}</h4>,
[BLOCKS.HEADING_5]: (node, key, next) => <h5>{next(node.content, key, next)}</h5>,
[BLOCKS.HEADING_6]: (node, key, next) => <h6>{next(node.content, key, next)}</h6>,
[BLOCKS.EMBEDDED_ENTRY]: (node, key, next) => <div>{next(node.content, key, next)}</div>,
[BLOCKS.UL_LIST]: (node, key, next) => <ul>{next(node.content, key, next)}</ul>,
[BLOCKS.OL_LIST]: (node, key, next) => <ol>{next(node.content, key, next)}</ol>,
[BLOCKS.LIST_ITEM]: (node, key, next) => <li>{next(node.content, key, next)}</li>,
[BLOCKS.QUOTE]: (node, key, next) => <blockquote>{next(node.content, key, next)}</blockquote>,
[BLOCKS.HR]: (node, key) => <hr>,
[INLINES.ASSET_HYPERLINK]: (node, key) => defaultInline(INLINES.ASSET_HYPERLINK, node, key),
[INLINES.ENTRY_HYPERLINK]: (node, key) => defaultInline(INLINES.ENTRY_HYPERLINK, node, key),
[INLINES.EMBEDDED_ENTRY]: (node, key) => defaultInline(INLINES.EMBEDDED_ENTRY, node, key),
[INLINES.HYPERLINK]: (node, key, next) => {
return (<a href="{node.data.uri}">{next(node.content, key, next)}</a>)
},
text: ({ marks, value }, key, markRenderer) => {
return marks.length ? (
marks.reduce((aggregate, mark, i) => markRenderer[mark.type](aggregate, `${key}-${i}`), value)
) : value
}
}
const renderNodeList = (nodes, key, next) => {
return nodes.map((node, i) => renderNode(node, `${key}-${i}`, next))
}
const renderNode = (node, key, next) => {
const nodeRenderer = next.node
if (helpers.isText(node)) {