diff --git a/README.md b/README.md index 45e6814..1b16a01 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # 🤖 automd -[![npm version][npm-version-src]][npm-version-href] -[![npm downloads][npm-downloads-src]][npm-downloads-href] + + +[![npm version](https://img.shields.io/npm/v/automd)](https://npmjs.com/package/automd) +[![npm downloads](https://img.shields.io/npm/dm/automd)](https://npmjs.com/package/automd) + + Your automated markdown maintainer! @@ -20,10 +24,8 @@ Automd scans for the annotation comments within the markdown document and update The syntax is like this: -```md - - -``` + + ### Using CLI @@ -172,6 +174,39 @@ The `pm-x` generator generates commands for running a package through JavaScript - `name`: The package name (by default tries to read from the `name` field in `package.json`). - `usage`: An additional string appended at the end of each command suggesting usage. (defaults to `""`). +### `badges` + +The `badges` generator generates badges for npm version, npm downloads and some optional ones like codecov and bundle. + +#### Usage + + + + +**Updated Result:** + + + + [![npm version](https://img.shields.io/npm/v/defu)](https://npmjs.com/package/defu) + [![npm downloads](https://img.shields.io/npm/dm/defu)](https://npmjs.com/package/defu) + [![bundle size](https://img.shields.io/bundlephobia/minzip/defu)](https://bundlephobia.com/package/defu) + [![codecov](https://img.shields.io/codecov/c/gh/unjs/automd)](https://codecov.io/gh/unjs/automd) + + + +#### Arguments + +- `name`: The npm package name. By default tries to infer from `package.json`. +- `github`: Github repository name. By default tries to infer from `package.json`. +- `bundlephobia`: Show [bundle-phobia](https://bundlephobia.com/) badge (requires `name`). +- `codecov`: Enable [codecov](https://codecov.io) badge (requires `github`). +- `no-npmDownloads`: Hide npm downloads badge. +- `no-npmVersion`: Hide npm version badge. +- `provider`: Can be one of `shields` (for [shields.io](https://shields.io/)) or `badgen` / `badgenClassic` (for [badgen.net](https://badgen.net/)). Default is `badgen`. + +> [!TIP] +> You can use additional `style`, `labelColor` and `color` args for `shields` provider for example: `provider=shields style=flat-square labelColor=f0db4f color=18181b`. + ## Development - Clone this repository @@ -186,10 +221,3 @@ The `pm-x` generator generates commands for running a package through JavaScript Made with 💛 Published under [MIT License](./LICENSE). - - - -[npm-version-src]: https://img.shields.io/npm/v/automd?style=flat&colorA=18181B&colorB=F0DB4F -[npm-version-href]: https://npmjs.com/package/automd -[npm-downloads-src]: https://img.shields.io/npm/dm/automd?style=flat&colorA=18181B&colorB=F0DB4F -[npm-downloads-href]: https://npmjs.com/package/automd diff --git a/package.json b/package.json index d1a9a3c..ce598be 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ ], "scripts": { "automd": "jiti src/cli.ts", - "build": "unbuild", + "build": "pnpm automd && unbuild", "dev": "vitest", "play": "pnpm automd --dir playground", "lint": "eslint --cache --ext .ts,.js,.mjs,.cjs . && prettier -c src", @@ -36,6 +36,7 @@ "c12": "^1.6.1", "citty": "^0.1.5", "consola": "^3.2.3", + "defu": "^6.1.4", "destr": "^2.0.2", "magic-string": "^0.30.7", "omark": "^0.1.0", diff --git a/playground/README.md b/playground/README.md index 6612dd4..7717b63 100644 --- a/playground/README.md +++ b/playground/README.md @@ -1,3 +1,14 @@ +# automd playground + + + +[![npm version](https://img.shields.io/npm/v/defu)](https://npmjs.com/package/defu) +[![npm downloads](https://img.shields.io/npm/dm/defu)](https://npmjs.com/package/defu) +[![bundle size](https://img.shields.io/bundlephobia/minzip/defu)](https://bundlephobia.com/package/defu) +[![codecov](https://img.shields.io/codecov/c/gh/unjs/automd)](https://codecov.io/gh/unjs/automd) + + + ## Usage @@ -50,4 +61,5 @@ Adds two numbers together. add(1, 2); // 3 ``` + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8383f24..12531dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: consola: specifier: ^3.2.3 version: 3.2.3 + defu: + specifier: ^6.1.4 + version: 6.1.4 destr: specifier: ^2.0.2 version: 2.0.2 diff --git a/src/_utils.ts b/src/_utils.ts index 6115464..d4122bb 100644 --- a/src/_utils.ts +++ b/src/_utils.ts @@ -1,20 +1,37 @@ -import { readPackageJSON } from "pkg-types"; +import { readPackageJSON, type PackageJson } from "pkg-types"; import _consola from "consola"; +import { defu } from "defu"; export const consola = _consola.withTag("automd"); -export async function getPkg( - dir: string, - input: { name?: string; version?: string } = {}, -) { - if (input.name && input.version) { - return input; - } +export async function getPkg(dir: string, input: Record = {}) { const pkg = await readPackageJSON(dir).catch(() => undefined); - return { - name: process.env.npm_package_name, - version: process.env.npm_package_name, - ...pkg, - ...input, - }; + return defu( + { + name: input.name, + version: input.version, + github: input.github || input.gh, + }, + { + name: pkg?.name, + version: pkg?.version, + github: _getGitRepo(pkg?.repository), + }, + { + name: process.env.npm_package_name, + version: process.env.npm_package_version, + }, + ); +} + +function _getGitRepo(repo: PackageJson["repository"]) { + const url = typeof repo === "string" ? repo : repo?.url; + if (!url || typeof url !== "string") { + return; + } + const match = + /(?:https:\/\/github\.com\/|gh:|github:|)([\w-]+)\/([\w-]+)/.exec(url); + if (match && match[1] && match[2]) { + return `${match[1]}/${match[2]}`; + } } diff --git a/src/generators/badges.ts b/src/generators/badges.ts new file mode 100644 index 0000000..6975263 --- /dev/null +++ b/src/generators/badges.ts @@ -0,0 +1,106 @@ +import { image, link } from "omark"; +import { defineGenerator } from "../generator"; +import { getPkg } from "../_utils"; + +type BadgeType = keyof typeof badgeTypes; +type BadgeProvider = Record & { _params?: string[] }; + +const badgeTypes = { + npmVersion: { + name: "npm version", + to: "https://npmjs.com/package/{name}", + }, + npmDownloads: { + name: "npm downloads", + to: "https://npmjs.com/package/{name}", + }, + bundlephobia: { + name: "bundle size", + to: "https://bundlephobia.com/package/{name}", + }, + codecov: { + name: "codecov", + to: "https://codecov.io/gh/{github}", + }, +}; + +const badgeProviders = >{ + shields: { + _params: ["style", "color", "labelColor"], + npmVersion: "https://img.shields.io/npm/v/{name}", + npmDownloads: "https://img.shields.io/npm/dm/{name}", + bundlephobia: "https://img.shields.io/bundlephobia/minzip/{name}", + codecov: "https://img.shields.io/codecov/c/gh/{github}", + }, + badgen: { + npmVersion: "https://flat.badgen.net/npm/v/{name}", + npmDownloads: "https://flat.badgen.net/npm/dm/{name}", + bundlephobia: "https://flat.badgen.net/bundlephobia/minzip/{name}", + codecov: "https://flat.badgen.net/codecov/c/github/{github}", + }, + badgenClassic: { + npmVersion: "https://badgen.net/npm/v/{name}", + npmDownloads: "https://badgen.net/npm/dm/{name}", + bundlephobia: "https://badgen.net/bundlephobia/minzip/{name}", + codecov: "https://badgen.net/codecov/c/github/{github}", + }, +}; + +export const badges = defineGenerator({ + name: "badges", + async generate({ config, args }) { + const pkg = await getPkg(config.dir, args); + const ctx: Record = { + name: pkg.name, + github: pkg.github, + ...args, + }; + + const fillStr = (str: string) => + str.replace(/{(\w+)}/g, (_, key) => ctx[key] || ""); + + const provider = badgeProviders[args.provider] || badgeProviders.shields; + const providerParams = (provider._params || []) + .filter((key) => ctx[key]) + .map( + (key) => `${encodeURIComponent(key)}=${encodeURIComponent(ctx[key])}`, + ) + .join("&"); + + const badges = { + npmVersion: { + enabled: ctx.name, + ...badgeTypes.npmVersion, + }, + npmDownloads: { + enabled: ctx.name, + ...badgeTypes.npmDownloads, + }, + bundlephobia: { + enabled: args.bundlephobia && ctx.name, + ...badgeTypes.bundlephobia, + }, + codecov: { + enabled: args.codecov && ctx.github, + ...badgeTypes.codecov, + }, + } as const; + + const md: string[] = []; + + for (const [badgeType, badge] of Object.entries(badges)) { + if (!badge.enabled || !provider[badgeType as BadgeType]) { + continue; + } + const to = fillStr(badge.to); + const imgURL = + fillStr(provider[badgeType as BadgeType]) + + (providerParams ? `?${providerParams}` : ""); + md.push(link(to, image(imgURL, badge.name))); + } + + return { + contents: md.join("\n"), + }; + }, +}); diff --git a/src/generators/index.ts b/src/generators/index.ts index 29721a8..2a9759a 100644 --- a/src/generators/index.ts +++ b/src/generators/index.ts @@ -1,9 +1,11 @@ import { Generator } from "../generator"; import { jsdocs } from "./jsdocs"; +import { badges } from "./badges"; import { pmX, pmInstall } from "./pm"; export default { jsdocs, + badges, "pm-install": pmInstall, "pm-x": pmX, } as Record;