/* `autoLinkFavicons` feature prepends a favicon image (from Google's favicon service) to external links whose text is a plain URL or contains only inline emphasis (``/``) — skipping any link already decorated with an `↗` marker. For each qualifying link the link text is cleaned (protocol prefix and trailing slash stripped; domain portion removed when significant path text remains), then wrapped in the original `` tag preceded by ``. Any HTML already present in the link text is wrapped in a `` so the favicon image stays a direct child of ``. Only `.html` output files are processed. > Compatible with: https://blades.ninja/css/link-icon/ ← this link is a live example! ```js */ export function isExternalUrl(url) { return /^https?:\/\//.test(url); } export function cleanLinkText(linkText) { return linkText .trim() .replace(/^https?:\/\//, "") .replace(/\/$/, ""); } export function getExtraAttrs(attrs, defaults) { return Object.entries(defaults) .map(([key, value]) => { const regex = new RegExp(`\\b${key}=`, "i"); return regex.test(attrs) ? "" : ` ${key}="${value}"`; }) .join(""); } export function buildFaviconLink(attrs, domain, text) { const extraAttrs = getExtraAttrs(attrs, { title: domain, target: "_blank", rel: "noopener noreferrer", }); const wrappedText = /<[a-z]/i.test(text) ? `${text}` : text; return ` ${wrappedText}`; } export function transformLink(match, attrs, url, linkText) { try { const domain = new URL(url).hostname; if (isExternalUrl(url) && !linkText.includes("↗")) { const cleaned = cleanLinkText(linkText); const stripped = cleaned.replace(domain, ""); const label = linkText.trim() === url && stripped.length > 2 ? stripped : cleaned; return buildFaviconLink(attrs, domain, label); } } catch (e) { // URL parsing failed — fall through and return original match } return match; } export function replaceLinksInHtml(content, transformer) { return content.replace( /]*href=["']([^"']+)["'][^>]*)>([^<]*(?:<\/?(?:em|strong|code)>[^<]*)*)<\/a>/gi, transformer, ); } export default function (eleventyConfig) { eleventyConfig.addTransform("autoLinkFavicons", function (content) { if (this.page.outputPath && this.page.outputPath.endsWith(".html")) { return replaceLinksInHtml(content, transformLink); } return content; }); } //```