@broberg/gravatar

中文文档
0.2.1发布于 2026/08/23MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 3005

Isomorphic Gravatar helper (SHA-256) + initials fallback. Headless core + React and Preact adapter components with 3-tier fallback: uploaded picture → Gravatar → generated initials.

原始使用文档
文档目录4 节
  1. gravatarLookup() — three outcomes, because there are three
  2. getInitials() — letters, not characters
  3. The core is async , on purpose
  4. API

@broberg/gravatar

Gravatar URLs and avatar initials for the fleet. Zero runtime dependencies, isomorphic.

npm i @broberg/gravatar
import { gravatarUrl, gravatarLookup, getInitials } from "@broberg/gravatar";

await gravatarUrl("[email protected]", { size: 80, default: "404" });
await gravatarLookup("[email protected]");   // 'yes' | 'no' | 'unknown'
getInitials("Christian Broberg");          // 'CB'

Also ships @broberg/gravatar/react and @broberg/gravatar/preact.

gravatarLookup() — three outcomes, because there are three

const presence = await gravatarLookup("[email protected]");
if (presence !== "unknown") cache.set(email, presence);   // never cache a guess
ResponseResultMeaning
404nogenuinely no avatar
200yes
5xx · a throw · a timeout · a surprise statusunknowndo not cache this as a no

Why it exists (v0.2.0). The old boolean collapsed three facts into two: a 503 from Automattic and a dropped connection both came back false, which reads as "there is no picture".

And you cache that answer — you have to, or you ask Automattic on every page render. So a ten-second hiccup cost a user their avatar until the cache expired, with nothing at the call-site able to tell. Found by a consumer on the day they adopted this package.

gravatarExists() is unchanged for existing callers and still cannot tell those two apart — both are false. If you store its result, you are storing a guess on every failure. Use gravatarLookup for anything you cache.

getInitials() — letters, not characters

getInitials("Lens (verifikation)");   // 'LV'    (was 'L(' before v0.2.0)
getInitials(null, "[email protected]");   // 'X'     (was 'X@')
getInitials("  ");                    // '??'    (was two spaces)
getInitials("李 明");                  // '李明'
getInitials("José");                  // 'JO'

Splits on non-letter/non-digit, unicode-aware — so CJK and accented Latin work, which an ASCII-only test suite would never have caught.

The email branch takes the prefix before @. That is what its documentation always claimed; the code read the whole address and only looked right because most addresses happen to begin with two letters.

An email in the name slot works (v0.2.1). getInitials("[email protected]") → CB, identical to getInitials(null, "[email protected]") — because navn = bruger.navn || bruger.email is an ordinary call-site and the two arguments must agree. Detection is conservative: exactly one @, non-empty and whitespace-free on both sides, so "Anne @ Hansen" stays a name.

0.2.0 got this wrong and shipped it: every address in the name slot came out ending in the TLD's first letter ([email protected] → CD). The acceptance criterion that should have caught it asserted the same string in the email argument only — the claim was about the common case, the test was about one argument position, and both were green.

Known limitation, deliberate. getInitials("Jens Hansen, direktør") returns JD — it takes the title as the surname. Truncating at the first comma would fix the Danish "Name, Title" form and break the equally common "Surname, Firstname" export. Two conventions, opposite fixes, and nothing in the string to tell them apart. Left alone rather than guessed at.

The core is async, on purpose

gravatarHash and gravatarUrl return promises because they use crypto.subtle — the one hashing API that exists in Node, Bun, Deno, workers and the browser.

A Node-only consumer expects a synchronous createHash and will be surprised. That is the isomorphism tax, and it is deliberate: the alternative is two code paths and a bundler condition on every consumer.

API

Export
gravatarHash(email)SHA-256 of the trimmed, lowercased address
gravatarUrl(email, { size?, default? })the full image URL
gravatarLookup(email, size?)'yes' | 'no' | 'unknown'
gravatarExists(email, size?)boolean — lossy; see above
getInitials(name?, email?)up to two uppercase characters, or '??'

版本与发布记录

@broberg/gravatar 共发布 3 个版本,首次发布于 2026/06/30;过去 12 个月发布了 3 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.1latest2026/08/232 个月前
0.2.02026/08/232 个月前
0.1.02026/06/304 个月前

关于 @broberg/gravatar 的常见问题

@broberg/gravatar 是什么?

Isomorphic Gravatar helper (SHA-256) + initials fallback. Headless core + React and Preact adapter components with 3-tier fallback: uploaded picture → Gravatar → generated initials.

如何安装 @broberg/gravatar?

在项目目录运行 npm install @broberg/gravatar,或使用 pnpm add / yarn add / bun add。

@broberg/gravatar 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@broberg/gravatar 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@broberg/gravatar 可以商用吗?

@broberg/gravatar 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@broberg/gravatar 的下载量有多少?

根据 npm 官方下载统计,@broberg/gravatar 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,005 次,日均约 100 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@broberg/gravatar 还在维护吗?

最新版本 0.2.1 发布于 2026/08/23(2 个月前);至今共发布 3 个版本,其中过去 12 个月发布了 3 个;首次发布于 2026/06/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。