#教程 dw, dm, dy, d18m 是何意?万物可 Badge | 定制漂亮精致小徽章,打造眼前一亮 README

最近看到一个开源库 sse-stuntman 的徽章独具一格:

就在想我的项目也能用上就好了。

平常我们的徽章都是固定的配色、固定 logo 甚至固定的文字。

而这个库的徽章新颖之处在于,logo 是自定义的(coverage 的 logo 是 CS),logo 颜色,dependencies 背景色黄色都是自定义。这是如何做到的呢?

平常我们用的最多的是 npm 下载量徽章,其实 downloads 徽章支持四种统计维度:

`dw`, `dm`, `dy`, `d18m` 最近 1 周 / 1 月 / 1 年 / 18 个月下载量

除了展示 npm 下载量还支持多达 73 项服务的下载量!

学完后我们甚至可以打造一个天气 badge。

徽章原理

我们从两个维度来说。

从能力来说:徽章(Badge)是 img.shields.io 公司提供的图片服务,分成静态徽章和动态徽章(后者依赖该公司服务端提供数据能力,比如 npm 的下载量)。

从格式来说:徽章其实是一段 markdown 代码,图片格式而已 ![alt](src)。

当然 HTML 片段也是合法的 markdown,可以被 github 或掘金等平台支持,故也可以是 <img alt="[alt]" src="<src>" />(只有 src 必选,但建议加 alt 这样即使图片 broken 也能展示图片含义)。

徽章拆解

静态徽章

徽章分成两部分,path 和 query。

https://img.shields.io/badge/label-message-greenyellow 这种格式称为静态徽章,即里面的文字和颜色都是固定的,可以看出 path 包含三元素"label message color",这是我们可以定制的部分。

当没有动态服务可以满足时候就可以使用,比如 sse-stuntman 的依赖数量徽章,这个库以 0 依赖轻量级为特色,所以他加了一个 dependencies 0 的徽章。代码很简单:

arduino 复制代码
https://img.shields.io/badge/dependencies-0-green

但是目前渲染的是还和 sse-stuntman 不一样,少了 logo 以及左半部分背景色不是黄色。

我们还需要学习更多"Query 查询参数"。下面文字来自官方文档。

静态徽章仅接收一个必填路径参数,该参数编码内容分为以下两种格式:

  1. 标签、提示文本、颜色(Label, message and color),三者以短横线 - 分隔。示例: --- 对应地址:img.shields.io/badge/any_t...

  2. 仅提示文本与颜色(Message and color only),二者以短横线 - 分隔。示例: --- 对应地址:img.shields.io/badge/just%...

URL 传入字符 徽章展示字符
单下划线 _ 或 %20 空格
双下划线 __ 单下划线 _
双短横线 -- 单短横线 -

这里的意思是如果你想在 label 里面增加空格,你得写 %20,以此类推。

更多静态徽章示例

支持十六进制、RGB、RGBA、HSL、HSLA 色值以及 CSS 标准颜色名。 注意: 部分内置颜色名的色值与原生 CSS 标准色存在差异。完整颜色名列表可查阅 badge-maker 文档。

动态徽章

我们常见的动态徽章有 npm version 和 npm downloads。每一种动态徽章都有可交互 playground:

Dynamic badges 展示具体项目指标,目前 shields.io 为数百个服务提供了徽章。

动态徽章又分为内置服务和自定义。

内置服务是 shields.io 给开发者提供了现成能力,这是徽章具备的动态变化魔力的基础。

自定义又有 6 种格式。

动态 JSON 徽章

动态 JSON 徽章支持通过 JSONPath 选择器从任意 JSON 文档中提取任意字段值,并将该值展示在徽章上。

比如我们有一个 package.json url raw.githubusercontent.com/legend80s/p... 可以如此展示其 name query=%24.name 24% 是 $ 的转义:

img.shields.io/badge/dynam...

举个更加有趣的例子,实时北京天气预报

我们可以展示北京当前温度(注意是天气数据不是写死的是实时的,每天打开都不一样)

img.shields.io/badge/dynam...

体感温度:

把 temp_C 改成 FeelsLikeC 即可。

为什么知道这么写?

几个技术要点:

  1. url --- 必填。指向一份 JSON 文档
  2. query --- 必填。用于查询该 JSON 文档的 JSONPath 表达式。示例:$.name

对于北京天气 url 是 https://wttr.in/beijing?lang=zh-cn&format=j1,query 是 query=$.current_condition[0].temp_C,label 是 北京当前温度,摄氏度是通过 suffix=℃增加的。更多参数见 Dynamic JSON Badge。

Endpoint Badge

img.shields.io/endpoint?ur...

只要你的 your_api 返回如下格式就会展示对应内容。

json 复制代码
{ "schemaVersion": 1, "label": "hello", "message": "sweet world", "color": "orange" }

有什么用呢?当无论静态还是内置服务都无法展示徽章内数据,因为这些数据可能存在你的服务器,就可以开放一个符合返回格式的 API endpoint。就是这么简单。

回顾下 Path 和 Query:

Path

/badge/ 都是静态 badge,动态 badge 服务不同 path 不同。举例:

Query

我们把 dependencies 0 徽章源码拿出来

ini 复制代码
https://img.shields.io/badge/dependencies-0-green?logo=npm&logoColor=212121&labelColor=ffc44e

问号后面的就是 query

ini 复制代码
?logo=npm&logoColor=212121&labelColor=ffc44e

现在可以看到 logo logoColor labelColor 如何定制。那么还有哪些参数呢?

参数 说明
style string 类型 可选值:flat、flat-square、plastic、for-the-badge、social 如未指定,此徽章默认样式为 flat 示例:flat
logo string 类型 来自 Simple Icons 的图标标识(slug)。点击 simple-icons 上的图标标题即可复制其 slug,也可在 simple-icons 仓库的 slugs.md 文件中查找。 示例:appveyor
logoColor string 类型 图标的颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。仅适用于 Simple Icons 图标,不适用于自定义图标。 示例:violet
logoSize string 类型 设置 auto 可使图标自适应缩放。适用于部分较宽的图标(如 amd、amg)。仅适用于 Simple Icons 图标,不适用于自定义图标。 示例:auto
label string 类型 覆盖左侧默认文本(空格或特殊字符需要 URL 编码!) 示例:healthiness
labelColor string 类型 左侧部分的背景颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。 示例:abcdef
color string 类型 右侧部分的背景颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。 示例:fedcba
cacheSeconds string 类型 HTTP 缓存时长(规则会自动为每个徽章推断默认值,低于默认值的设置将被忽略)。 示例:3600
link string[] 类型 指定点击徽章左侧/右侧时的跳转行为。注意:此功能仅在将徽章嵌入 <object> HTML 标签时有效,不适用于 <img> 标签或标记语言。

上面是通用参数,不同服务还有自己的参数,比如 npm version 可以指定 registry(公司内部包就可以派上用场了)。

md 复制代码
| **`registry_uri`** | 示例:`https://registry.npmjs.com` |

定制与众不同的徽章

接下来我们把 sse-stuntman 这个库的徽章源码抠出来学习,然后复制到自己的 README,并定制成具有自己项目印记的小徽章(badge)。

md 复制代码
<!-- https://github.com/legend80s/sse-stuntman/blob/main/README.md -->

<p>
  <a href="https://www.npmjs.com/package/sse-stuntman" target="_blank">
    <img src="https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan" alt="npm version" />
  </a>

  <a href="https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies" target="_blank">
    <img alt="0 dependencies" src="https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121" />
  </a>

  <a href="https://www.npmjs.com/package/sse-stuntman">
    <img src="https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan" alt="npm downloads" />
  </a>

  ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
</p>

掘金也支持,比如下面的徽章就是上述代码渲染的,注释不是我截图,是实实在在通过 HTML 代码渲染的,是动态的,当 sse-stuntman 的下载量变化了,你再来这篇文章看,会发现数字是事实同步的。

这就是 badge 的魔力。它不仅仅是一个静态的图片。

前端开发者特别容易理解

但是上述有个问题,就是 badge 之间会有下划线,这是因为 <a /> 链接导致的,改成 markdown link 语法即可:

ruby 复制代码
    <p>

      [![NPM Version](https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)
      
      [![0 dependencies](https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121)](https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies)
      
      [![NPM Downloads](https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)

      ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
    </p>

注意此种写法第一个 bage 和 <p> 必须留有至少一个空行,否则 badge 将展示成源码而非图片。

还可以优化下,让 badge 居中 <div align="center">。其实这个技巧也可以用在掘金里面。

ini 复制代码
    <div align="center">

      [![NPM Version](https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)
      
      [![0 dependencies](https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121)](https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies)
      
      [![NPM Downloads](https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)

      ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
    </p>

本系列每 1 个观点都追溯到 1 行源码、1 段官方文档。

相关推荐
爱写代码的倒霉蛋1 小时前
新手如何借助agent改造github项目(保姆级教程)
github·新手友好·改造项目
u1301301 小时前
GitHub 热榜项目:日榜(2026-10-07)
驱动开发·github
高频因子挖掘机2 小时前
量化选股到底要不要每天拉全市场股票?从全市场扫描到候选池的行情数据设计
后端·github·api
miofly2 小时前
GitHub 日榜趋势速报 | 2026-10-08
开源·github
Skrrapper2 小时前
AI项目实战日记ep2:把 GitHub Issue 的第一轮脏活交给 AI:做一个 Issue 分诊助手
人工智能·github·issue
高频因子挖掘机2 小时前
复权价格怎么算?从除权因子、时间方向到量化回测避坑
后端·github·api
Maynor在掘金17 小时前
Nano Banana 2.1 来了!21 个真实案例 + 公开提示词,这份 Awesome 合集请收好
github
miofly17 小时前
ChatGPT 账号用户可免费使用 Auto-review 双智能体审查功能
开源·github
高频因子挖掘机17 小时前
第一次补历史行情:按股票拆,还是按日期拆请求?
后端·github·api