59 lines
1.3 KiB
TypeScript
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;
|
|
},
|
|
);
|
|
};
|