Organize/components/markdown/markdown-widgets.tsx

36 lines
1.4 KiB
TypeScript

"use client";
import dynamic from "next/dynamic";
import type { ComponentProps } from "react";
import type { RehypeRewriteOptions } from "rehype-rewrite";
// Markdown editing/rendering touches the DOM directly and has no
// server-render value, so both pieces are loaded client-side only and kept
// out of the initial board bundle. Shared here so every place that needs
// markdown (group notes, to-do details) uses the exact same editor/preview
// widgets instead of each declaring its own dynamic import.
export const MDEditor = dynamic(() => import("@uiw/react-md-editor"), { ssr: false });
const RawMarkdownPreview = dynamic(
() => import("@uiw/react-md-editor").then((mod) => mod.default.Markdown),
{ ssr: false }
);
// Rewrites every rendered <a> to open in a new tab -- clicking a link in a
// note/to-do preview would otherwise navigate the whole app away from the
// board. `noopener noreferrer` keeps the new tab from being able to reach
// back into this one via `window.opener`.
const openLinksInNewTab: RehypeRewriteOptions["rewrite"] = (node) => {
if (node.type === "element" && node.tagName === "a") {
node.properties = {
...node.properties,
target: "_blank",
rel: ["noopener", "noreferrer"],
};
}
};
export function MarkdownPreview(props: ComponentProps<typeof RawMarkdownPreview>) {
return <RawMarkdownPreview {...props} rehypeRewrite={openLinksInNewTab} />;
}