import React from "react"; import ReactMarkdown from "react-markdown"; import remarkMath from "remark-math"; import rehypeKatex from "rehype-katex"; import rehypeRaw from "rehype-raw"; import rehypeSanitize, { defaultSchema } from "rehype-sanitize"; import remarkGfm from "remark-gfm"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { okaidia } from "react-syntax-highlighter/dist/esm/styles/prism"; import "katex/dist/katex.min.css"; import "./MarkdownView.css"; import {useLinks} from "../../utils/queries/markdown-queries"; const Translate = ({variable, value}) => { if (variable.type.base_type === "markdown" || variable.type.base_type === "string" || variable.type.base_type === "enum") { return value; } if(variable.type.base_type === "list"){ if (!variable.type.extend_type) return []; return (value || []).map((item, index) => Translate({ variable: {name: index, type: variable.type.extend_type}, value: item, })).map((item) => variable.type.definition.iter_layout.replaceAll('', item)).join(""); } if(variable.type.base_type === "template"){ return ParseTemplate({ template: variable.type.definition.template, variables: value }); } }; const ParseTemplate = ({template, variables}) => { if(!template || !Array.isArray(template.parameters)) return ''; const vars = variables || {}; let res = template.layout ?? ''; for (const parameter of template.parameters) { res = res.replaceAll(`<${parameter.name}/>`, Translate({ variable: parameter, value: vars[parameter.name] })); } return res; }; // Markdown content is authored by users and rendered for everyone // (including the unauthenticated /pg/* route), so raw HTML must be // sanitized to prevent stored XSS. className is kept on code/span/div so // syntax highlighting and KaTeX (which runs after sanitize) still work; // scripts, event handlers and javascript: URLs are stripped. const sanitizeSchema = { ...defaultSchema, attributes: { ...defaultSchema.attributes, code: [...(defaultSchema.attributes?.code || []), ["className"]], span: [...(defaultSchema.attributes?.span || []), ["className"]], div: [...(defaultSchema.attributes?.div || []), ["className"]], }, }; const MarkdownView = ({ content, template, height="auto" }) => { const {data: links, isLoading} = useLinks(); if (isLoading) return (

Loading...

); const linkDefinitions = "\n\n" + links.join("\n"); const _template = template || { parameters: [ { name: "markdown", type: { base_type: "markdown", definition: {} } } ], layout: "", title: "default" }; return (
{String(children).replace(/\n$/, "")} ) : ( {children} ); }, }} />
); }; export default MarkdownView;