4cddfcf2f3
Backend Tests / Tests (other) (push) Failing after 1s
Backend Tests / Static Checks (push) Failing after 2s
Backend Tests / Tests (internal) (push) Failing after 2s
Backend Tests / Tests (server) (push) Failing after 1s
Backend Tests / Tests (store) (push) Failing after 1s
Build Canary Image / build-frontend (push) Failing after 1s
Frontend Tests / Lint (push) Failing after 1s
Build Canary Image / build-push (linux/amd64) (push) Has been skipped
Build Canary Image / build-push (linux/arm64) (push) Has been skipped
Build Canary Image / merge (push) Has been skipped
Frontend Tests / Build (push) Failing after 1s
Release Please / release-please (push) Failing after 0s
Proto Linter / Lint Protos (push) Failing after 2s
64 lines
1.9 KiB
TypeScript
64 lines
1.9 KiB
TypeScript
import type { Element } from "hast";
|
|
import { useLinkPreviewEnabled } from "@/contexts/ViewContext";
|
|
import { markdownStyles } from "@/lib/markdownStyles";
|
|
import { cn } from "@/lib/utils";
|
|
import LinkMetadataCard from "../LinkMetadataCard";
|
|
import { useMarkdownRenderContext } from "../MarkdownRenderContext";
|
|
import type { ReactMarkdownProps } from "./types";
|
|
|
|
interface ParagraphProps extends React.HTMLAttributes<HTMLParagraphElement>, ReactMarkdownProps {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function getSingleLinkHref(node?: Element): string | undefined {
|
|
if (!node || node.tagName !== "p") {
|
|
return undefined;
|
|
}
|
|
|
|
const meaningfulChildren = node.children.filter((child) => {
|
|
return !(child.type === "text" && child.value.trim() === "");
|
|
});
|
|
|
|
if (meaningfulChildren.length !== 1) {
|
|
return undefined;
|
|
}
|
|
|
|
const onlyChild = meaningfulChildren[0];
|
|
if (onlyChild.type !== "element" || onlyChild.tagName !== "a") {
|
|
return undefined;
|
|
}
|
|
|
|
const href = onlyChild.properties?.href;
|
|
if (typeof href !== "string") {
|
|
return undefined;
|
|
}
|
|
|
|
const meaningfulLinkChildren = onlyChild.children.filter((child) => {
|
|
return !(child.type === "text" && child.value.trim() === "");
|
|
});
|
|
|
|
if (meaningfulLinkChildren.length !== 1) {
|
|
return undefined;
|
|
}
|
|
|
|
const onlyLinkChild = meaningfulLinkChildren[0];
|
|
return onlyLinkChild.type === "text" && onlyLinkChild.value === href ? href : undefined;
|
|
}
|
|
|
|
export const Paragraph = ({ children, className, node, ...props }: ParagraphProps) => {
|
|
const { blockDepth } = useMarkdownRenderContext();
|
|
const linkPreviewEnabled = useLinkPreviewEnabled();
|
|
const href = blockDepth === 0 && linkPreviewEnabled ? getSingleLinkHref(node) : undefined;
|
|
const paragraph = (
|
|
<p className={cn(markdownStyles.paragraph, className)} {...props}>
|
|
{children}
|
|
</p>
|
|
);
|
|
|
|
if (href) {
|
|
return <LinkMetadataCard url={href} fallback={paragraph} />;
|
|
}
|
|
|
|
return paragraph;
|
|
};
|