stoat-for-desktop/components/markdown/plugins/remarkLinkify.ts

59 lines
1.3 KiB
TypeScript

import LinkifyIt from "linkify-it";
import { Plugin } from "unified";
import { visit } from "unist-util-visit";
const linkify = new LinkifyIt({
fuzzyLink: false,
});
export const remarkLinkify: Plugin = () => (tree) => {
visit(
tree,
"text",
(
node: { type: "text"; value: string },
idx,
parent: { children: unknown[] },
) => {
const links = linkify.match(node.value);
if (links === null) return; // no matches
const newNodes: (
| { type: "text"; value: string }
| {
type: "link";
children: { type: "text"; value: string }[];
}
)[] = [
{
type: "text",
value: node.value.slice(0, links[0].index),
},
...links.flatMap((link, idx) => [
{
type: "link" as const,
url: link.url,
title: link.text,
children: [
{
type: "text" as const,
value: link.text,
},
],
},
{
type: "text" as const,
value: node.value.slice(
link.lastIndex,
links[idx + 1]?.index ?? node.value.length,
),
},
]),
];
parent.children.splice(idx, 1, ...newNodes);
return idx + newNodes.length;
},
);
};