markdown.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. """Markdown component."""
  2. import textwrap
  3. from typing import List
  4. from pynecone.components.component import Component
  5. from pynecone.var import BaseVar
  6. class Markdown(Component):
  7. """A markdown component."""
  8. library = "react-markdown"
  9. tag = "ReactMarkdown"
  10. @classmethod
  11. def create(cls, *children, **props) -> Component:
  12. """Create a markdown component.
  13. Args:
  14. children: The children of the component.
  15. props: The properties of the component.
  16. Returns:
  17. The markdown component.
  18. """
  19. assert (
  20. len(children) == 1
  21. ), "Markdown component must have exactly one child containing the markdown source."
  22. src = textwrap.dedent(children[0])
  23. return super().create(src, **props)
  24. def _get_imports(self):
  25. imports = super()._get_imports()
  26. imports["@chakra-ui/react"] = {
  27. "Heading",
  28. "Code",
  29. "Text",
  30. "Link",
  31. "UnorderedList",
  32. "OrderedList",
  33. "ListItem",
  34. }
  35. imports["react-syntax-highlighter"] = {"Prism"}
  36. imports["remark-math"] = {"remarkMath"}
  37. imports["remark-gfm"] = {"remarkGfm"}
  38. imports["rehype-katex"] = {"rehypeKatex"}
  39. imports["rehype-raw"] = {"rehypeRaw"}
  40. imports[""] = {"katex/dist/katex.min.css"}
  41. return imports
  42. def _render(self):
  43. return (
  44. super()
  45. ._render()
  46. .add_props(
  47. components={
  48. "h1": "{({node, ...props}) => <Heading size='2xl' {...props} />}",
  49. "h2": "{({node, ...props}) => <Heading size='xl' {...props} />}",
  50. "h3": "{({node, ...props}) => <Heading size='lg' {...props} />}",
  51. "ul": "{UnorderedList}",
  52. "ol": "{OrderedList}",
  53. "li": "{ListItem}",
  54. "p": "{Text}",
  55. "a": "{Link}",
  56. "code": """{({node, inline, className, children, ...props}) =>
  57. {
  58. const match = (className || '').match(/language-(?<lang>.*)/);
  59. return !inline ? (
  60. <Prism
  61. children={String(children).replace(/\n$/, '')}
  62. language={match ? match[1] : ''}
  63. {...props}
  64. />
  65. ) : (
  66. <Code {...props}>
  67. {children}
  68. </Code>
  69. );
  70. }}""".replace(
  71. "\n", " "
  72. ),
  73. },
  74. remark_plugins=BaseVar(name="[remarkMath, remarkGfm]", type_=List[str]),
  75. rehype_plugins=BaseVar(
  76. name="[rehypeKatex, rehypeRaw]", type_=List[str]
  77. ),
  78. )
  79. )