import { useFrontmatter } from "@rspress/core/runtime" // MD5 — self-contained, works in any JS environment function md5Hex(message: string): string { const S = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, ] const T: number[] = [] for (let i = 0; i < 64; i++) { T[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000) | 0 } const bytes: number[] = [] for (let i = 0; i < message.length; i++) { const c = message.charCodeAt(i) if (c < 0x80) bytes.push(c) else if (c < 0x800) { bytes.push(0xc0 | (c >> 6)) bytes.push(0x80 | (c & 0x3f)) } else { bytes.push(0xe0 | (c >> 12)) bytes.push(0x80 | ((c >> 6) & 0x3f)) bytes.push(0x80 | (c & 0x3f)) } } const bitLen = bytes.length * 8 bytes.push(0x80) while ((bytes.length + 8) % 64 !== 0) bytes.push(0) for (let i = 0; i < 4; i++) bytes.push((bitLen >>> (i * 8)) & 0xff) for (let i = 0; i < 4; i++) bytes.push(0) let a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476 for (let offset = 0; offset < bytes.length; offset += 64) { const M = new Array(16) for (let i = 0; i < 16; i++) { M[i] = bytes[offset + i * 4] | (bytes[offset + i * 4 + 1] << 8) | (bytes[offset + i * 4 + 2] << 16) | (bytes[offset + i * 4 + 3] << 24) } let A = a0, B = b0, C = c0, D = d0 for (let i = 0; i < 64; i++) { let F: number, g: number if (i < 16) { F = (B & C) | (~B & D) g = i } else if (i < 32) { F = (D & B) | (~D & C) g = (5 * i + 1) % 16 } else if (i < 48) { F = B ^ C ^ D g = (3 * i + 5) % 16 } else { F = C ^ (B | ~D) g = (7 * i) % 16 } F = (F + A + T[i] + M[g]) | 0 A = D D = C C = B B = (B + ((F << S[i]) | (F >>> (32 - S[i])))) | 0 } a0 = (a0 + A) | 0 b0 = (b0 + B) | 0 c0 = (c0 + C) | 0 d0 = (d0 + D) | 0 } return [a0, b0, c0, d0] .map( (x) => ((x >>> 0) & 0xff).toString(16).padStart(2, "0") + ((x >>> 8) & 0xff).toString(16).padStart(2, "0") + ((x >>> 16) & 0xff).toString(16).padStart(2, "0") + ((x >>> 24) & 0xff).toString(16).padStart(2, "0") ) .join("") } function gravatarUrl(email: string, size = 80): string { const normalized = email.trim().toLowerCase() const hash = md5Hex(normalized) return `https://cravatar.cn/avatar/${hash}?s=${size}&d=robohash&r=g` } interface AuthorInfo { name?: string email?: string } export function Author({ className }: { className?: string }) { const { frontmatter } = useFrontmatter() const author = frontmatter?.author as AuthorInfo | undefined if (!author?.name?.trim()) return null const src = author.email?.trim() ? gravatarUrl(author.email) : null return ( {src && {author.name}} {author.name} ) }