lens-blocks
componentlens-markdownsource: ok · hit
Lens Markdown
A Markdown renderer for Lens posts and comments, supporting mentions, links, and rich text formatting.
npx shadcn add "https://lensblocks.com/r/lens-markdown.json"free
Where it goes
comment
Use cases
community
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · light@lens-protocol/react@0.0.0-canary-20250820102520@lens-protocol/metadata@2.1.0react-markdown@9.0.3remark-gfm@4.0.1remark-breaks@4.0.0remark-linkify-regex@1.2.1strip-markdown@6.0.0
Registry dependencies
https://lensblocks.com/r/utils.json
Files4 · source cached 10/14/2026, 2:06:37 PM
registry/new-york/components/common/lens-markdown.tsx
// @ts-ignore
import linkifyRegex from "remark-linkify-regex";
import stripMarkdown from "strip-markdown";
import remarkGfm from "remark-gfm";
import remarkBreaks from "remark-breaks";
import { RegEx } from "@/registry/new-york/lib/regex";
import ReactMarkdown, { Components } from "react-markdown";
import { cn } from "@/lib/utils";
import { LensMentionLink } from "@/registry/new-york/components/common/lens-mention-link";
import { AccountMention, GroupMention } from "@lens-protocol/react";
import { LensTagLink } from "@/registry/new-york/components/common/lens-tag-link";
import { truncateUrl } from "@/registry/new-york/lib/lens-utils";
type Props = {
content: string;
className?: string;
mentions?: (AccountMention | GroupMention)[];
};
export const LensMarkdown = (props: Props) => {
const { content, className, mentions } = props;
const remarkPlugins = [
[
stripMarkdown,
{
keep: ["blockquote", "code", "delete", "emphasis", "inlineCode", "link", "list", "listItem", "strong"],
},
],
remarkGfm,
remarkBreaks,
linkifyRegex(RegEx.URL),
linkifyRegex(RegEx.MENTION),
linkifyRegex(RegEx.HASHTAG),
linkifyRegex(RegEx.CASHTAG),
];
const components: Components = {
// linkifyRegex will find mentions, hashtags, and cashtags, and replace them with a link
// here we are defining how to render that link
a: (props: any) => {
const mention = mentions?.find(mention => mention.replace.from === props.title);
if (mention) {
return <LensMentionLink mention={mention} />;
}
if (props.title?.startsWith("#") || props.title?.startsWith("$")) {
return <LensTagLink tag={props.title} />;
}
return (
<a {...props} target="_blank" rel="noopener noreferrer" className="font-bold hover:underline">
{truncateUrl(props.href)}
</a>
);
},
};
return (
<ReactMarkdown
remarkPlugins={remarkPlugins}
components={components}
className={cn("break-words hyphens-none line-clamp-6 whitespace-pre-wrap", className)}
>
{content}
</ReactMarkdown>
);
};
registry/new-york/components/common/lens-mention-link.tsx
import { ComponentProps } from "react";
import { AccountMention, GroupMention } from "@lens-protocol/react";
import { getUsernamePath } from "@/registry/new-york/lib/lens-utils";
type Props = {
mention: AccountMention | GroupMention;
href?: string;
};
type LinkProps = Omit<ComponentProps<"a">, "href">;
export const LensMentionLink = (props: Props & LinkProps) => {
if (props.mention.__typename === "GroupMention") {
const href = props.href ?? `/g/${props.mention.replace.from.replace("#", "")}`;
return (
<a {...props} href={href}>
{props.mention.replace.to}
</a>
);
}
const namespace = props.mention.namespace;
const href = props.href ?? getUsernamePath(props.mention.replace.to, namespace);
return (
<a {...props} href={href}>
{props.mention.replace.to.replace("@lens/", "@")}
</a>
);
};
registry/new-york/components/common/lens-tag-link.tsx
import { ComponentProps } from "react";
type Props = {
tag: string;
href?: string;
};
type LinkProps = Omit<ComponentProps<"a">, "href">;
export const LensTagLink = (props: Props & LinkProps) =>
props.href ? (
<a {...props} href={props.href}>
{props.tag}
</a>
) : (
<span className="font-bold">{props.tag}</span>
);
registry/new-york/lib/regex.ts
const regexLookbehindAvailable: boolean = ((): boolean => {
try {
return "ab".replace(/(?<=a)b/g, "c") === "ac";
} catch {
return false;
}
})();
const MATCH_BEHIND = regexLookbehindAvailable ? "(?<=^|\\s)" : "";
const MENTION_NAMESPACE = "\\w+\\/";
const MENTION_BODY = "([\\dA-Za-z]\\w{2,25})";
export const RegEx = {
CASHTAG: /(\$\w*[A-Za-z]\w*)/g,
HASHTAG: /(#\w*[A-Za-z]\w*)/g,
MENTION: new RegExp(`${MATCH_BEHIND}@${MENTION_NAMESPACE}${MENTION_BODY}`, "g"),
URL: /\b(http|https):\/\/([\p{L}\p{N}_-]+(?:(?:\.[\p{L}\p{N}_-]+)+))([\p{L}\p{N}_.,@?^=%&:\/~+#-]*[\p{L}\p{N}_@?^=%&\/~+#-])/gu,
};