sparkletown/sparkle

View on GitHub
src/components/organisms/RenderMarkdown/RenderMarkdownInner.tsx

Summary

Maintainability
A
3 hrs
Test Coverage
import React from "react";
import ReactMarkdown from "react-markdown";
import sanitize from "rehype-sanitize";
import emoji from "remark-emoji";
import externalLinks from "remark-external-links";
import glm from "remark-gfm";

import {
  MARKDOWN_BASIC_FORMATTING_TAGS,
  MARKDOWN_HEADING_TAGS,
  MARKDOWN_IMAGE_TAGS,
  MARKDOWN_LINK_TAGS,
  MARKDOWN_LIST_TAGS,
  MARKDOWN_PRE_CODE_TAGS,
} from "settings";

import { isTruthy } from "utils/types";

const REMARK_PLUGINS = [glm, emoji, externalLinks];
const REHYPE_PLUGINS = [sanitize];

export interface RenderMarkdownProps {
  text?: string;
  components?: object;
  allowBasicFormatting?: boolean;
  allowPreAndCode?: boolean;
  allowHeadings?: boolean;
  allowLinks?: boolean;
  allowImages?: boolean;
  allowLists?: boolean;
}

const _RenderMarkdownInner: React.FC<RenderMarkdownProps> = ({
  text,
  components,
  allowBasicFormatting = true,
  allowPreAndCode = true,
  allowHeadings = true,
  allowLinks = true,
  allowImages = true,
  allowLists = true,
}) => {
  const allowedElements: string[] = [
    ...(allowBasicFormatting ? MARKDOWN_BASIC_FORMATTING_TAGS : []),
    ...(allowHeadings ? MARKDOWN_HEADING_TAGS : []),
    ...(allowImages ? MARKDOWN_IMAGE_TAGS : []),
    ...(allowLinks ? MARKDOWN_LINK_TAGS : []),
    ...(allowLists ? MARKDOWN_LIST_TAGS : []),
    ...(allowPreAndCode ? MARKDOWN_PRE_CODE_TAGS : []),
  ].filter(isTruthy);

  if (!text) return null;

  return (
    <ReactMarkdown
      remarkPlugins={REMARK_PLUGINS}
      rehypePlugins={REHYPE_PLUGINS}
      linkTarget="_blank"
      allowedElements={allowedElements}
      components={components}
    >
      {text}
    </ReactMarkdown>
  );
};

export const RenderMarkdownInner = React.memo(_RenderMarkdownInner);