Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# markdown-magic-transform-badges

<!-- doc-gen BADGES style=for-the-badge collapse=true collapseLabel="More badges" collapseVisible=7 ciWorkflow="ci.yml" ciBranch="main" -->

[![npm version](https://img.shields.io/npm/v/markdown-magic-transform-badges.svg?style=for-the-badge)](https://www.npmjs.com/package/markdown-magic-transform-badges) [![actions status](https://img.shields.io/github/actions/workflow/status/ioncakephper/markdown-magic-transform-badges/ci.yml?branch=main&style=for-the-badge)](https://github.com/ioncakephper/markdown-magic-transform-badges/actions) [![license](https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge)](https://www.npmjs.com/package/markdown-magic-transform-badges) [![maintained](https://img.shields.io/github/commit-activity/y/ioncakephper/markdown-magic-transform-badges?style=for-the-badge)](https://github.com/ioncakephper/markdown-magic-transform-badges/graphs/commit-activity) [![npm downloads](https://img.shields.io/npm/dw/markdown-magic-transform-badges.svg?style=for-the-badge)](https://www.npmjs.com/package/markdown-magic-transform-badges) [![codecov](https://img.shields.io/codecov/c/github/ioncakephper/markdown-magic-transform-badges?branch=main&style=for-the-badge)](https://codecov.io/gh/ioncakephper/markdown-magic-transform-badges) [![release](https://img.shields.io/github/v/release/ioncakephper/markdown-magic-transform-badges?style=for-the-badge)](https://github.com/ioncakephper/markdown-magic-transform-badges/releases)

<details>
Expand Down Expand Up @@ -157,61 +156,58 @@ This project is licensed under the terms of the MIT License. See the [`LICENSE`]
## Helper Scripts

<!-- doc-gen SCRIPTS format=list -->

- `docs` — Generate documentation by processing README.md with markdown-magic. (line [12](./package.json#L12))
- `docs` — Generate documentation by processing README.md with markdown-magic. (line [13](./package.json#L13))

```bash
npx markdown-magic README.md --config ./markdown-magic.config.js
```

- `fix` — Automatically fix linting issues and format codebase. (line [7](./package.json#L7))
- `fix` — Automatically fix linting issues and format codebase. (line [8](./package.json#L8))

```bash
npm run lint:fix && npm run format && npm run format:package
```

- `format` — Format all project files using Prettier. (line [8](./package.json#L8))
- `format` — Format all project files using Prettier. (line [9](./package.json#L9))

```bash
prettier --write .
```

- `format:package` — Format the package.json file using Prettier. (line [9](./package.json#L9))
- `format:package` — Format the package.json file using Prettier. (line [10](./package.json#L10))

```bash
prettier --write package.json
```

- `lint` — Lint all project files to ensure code quality and consistency. (line [10](./package.json#L10))
- `lint` — Lint all project files to ensure code quality and consistency. (line [11](./package.json#L11))

```bash
eslint . --ext .js,.json,.yaml,.yml,.md
```

- `lint:fix` — Lint all project files and automatically fix issues where possible. (line [11](./package.json#L11))
- `lint:fix` — Lint all project files and automatically fix issues where possible. (line [12](./package.json#L12))

```bash
eslint . --ext .js,.json,.yaml,.yml,.md --fix
```

- `prep` — Prepare the project for publishing by generating docs and formatting code. (line [13](./package.json#L13))
- `prep` — Prepare the project for publishing by generating docs and formatting code. (line [14](./package.json#L14))

```bash
npm run docs && npm run fix
```

- `test` — Run the test suite using Jest. (line [6](./package.json#L6))
- `test` — Run the test suite using Jest. (line [7](./package.json#L7))

```bash
jest --passWithNoTests
```

<!-- end-doc-gen -->

## Repository Structure

<!-- doc-gen fileTree -->

```
└── markdown-magic-transform-badges/
├── .pretierrc.json
Expand All @@ -226,5 +222,4 @@ This project is licensed under the terms of the MIT License. See the [`LICENSE`]
├── README.md
└── RULES_OF_CONDUCT.md
```

<!-- end-doc-gen -->
53 changes: 29 additions & 24 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,35 +36,40 @@ module.exports = ({ transform, options, settings = {} }) => {
const name = pkg.name;

// helper to add named badges
const pushBadge = (key, md) => allBadges.push({ key, md });
const pushBadge = (key, md) => {
if (opts.excludeBadges && opts.excludeBadges.includes(key)) {
return; // Skip this badge if it's in the exclude list
}
allBadges.push({ key, md });
};
Comment on lines +39 to +44
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation for excluding badges is not fully robust and could lead to issues:

  1. Incorrect partial matching: If opts.excludeBadges is a string (e.g., from a markdown comment like excludeBadges="version"), using String.prototype.includes() could incorrectly exclude badges with partial matches (e.g., "npmVersion").
  2. Potential for runtime errors: If opts.excludeBadges is not a string or an array (e.g., a boolean or a number), the call to .includes() will throw a TypeError, crashing the process.

To make this feature more reliable, I suggest explicitly handling both arrays and comma-separated strings for the excludeBadges option, while safely ignoring other data types.

  const pushBadge = (key, md) => {
    let exclusions = [];
    if (Array.isArray(opts.excludeBadges)) {
      exclusions = opts.excludeBadges;
    } else if (typeof opts.excludeBadges === 'string') {
      exclusions = opts.excludeBadges.split(',').map(s => s.trim());
    }

    if (exclusions.includes(key)) {
      return; // Skip this badge if it's in the exclude list
    }
    allBadges.push({ key, md });
  };


if (name) {
pushBadge(
"npmVersion",
`[![npm version](https://img.shields.io/npm/v/${encodeURIComponent(
name,
name
)}.svg${style})](https://www.npmjs.com/package/${encodeURIComponent(
name,
)})`,
name
)})`
);
pushBadge(
"npmDownloads",
`[![npm downloads](https://img.shields.io/npm/dw/${encodeURIComponent(
name,
name
)}.svg${style})](https://www.npmjs.com/package/${encodeURIComponent(
name,
)})`,
name
)})`
);
}

if (pkg.license) {
pushBadge(
"license",
`[![license](https://img.shields.io/badge/license-${encodeURIComponent(
pkg.license,
pkg.license
)}-blue.svg${style})](https://www.npmjs.com/package/${encodeURIComponent(
name,
)})`,
name
)})`
);
}

Expand All @@ -84,62 +89,62 @@ module.exports = ({ transform, options, settings = {} }) => {
const workflowBranch = opts.ciBranch ?? pkg.ciBranch ?? "main";
pushBadge(
"actions",
`[![actions status](https://img.shields.io/github/actions/workflow/status/${owner}/${repoName}/${workflowFile}?branch=${workflowBranch}${styleAmp})](https://github.com/${ownerRepo}/actions)`,
`[![actions status](https://img.shields.io/github/actions/workflow/status/${owner}/${repoName}/${workflowFile}?branch=${workflowBranch}${styleAmp})](https://github.com/${ownerRepo}/actions)`
);

pushBadge(
"codecov",
`[![codecov](https://img.shields.io/codecov/c/github/${owner}/${repoName}?branch=${workflowBranch}${styleAmp})](https://codecov.io/gh/${ownerRepo})`,
`[![codecov](https://img.shields.io/codecov/c/github/${owner}/${repoName}?branch=${workflowBranch}${styleAmp})](https://codecov.io/gh/${ownerRepo})`
);

pushBadge(
"release",
`[![release](https://img.shields.io/github/v/release/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/releases)`,
`[![release](https://img.shields.io/github/v/release/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/releases)`
);
// Commit activity / maintained badge (yearly commits)
pushBadge(
"maintained",
`[![maintained](https://img.shields.io/github/commit-activity/y/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/graphs/commit-activity)`,
`[![maintained](https://img.shields.io/github/commit-activity/y/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/graphs/commit-activity)`
);
pushBadge(
"stars",
`[![stars](https://img.shields.io/github/stars/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/stargazers)`,
`[![stars](https://img.shields.io/github/stars/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/stargazers)`
);
pushBadge(
"forks",
`[![forks](https://img.shields.io/github/forks/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/network/members)`,
`[![forks](https://img.shields.io/github/forks/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/network/members)`
);
pushBadge(
"watchers",
`[![watchers](https://img.shields.io/github/watchers/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/watchers)`,
`[![watchers](https://img.shields.io/github/watchers/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/watchers)`
);
pushBadge(
"lastCommit",
`[![last commit](https://img.shields.io/github/last-commit/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/commits)`,
`[![last commit](https://img.shields.io/github/last-commit/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/commits)`
);
pushBadge(
"contributors",
`[![contributors](https://img.shields.io/github/contributors/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/graphs/contributors)`,
`[![contributors](https://img.shields.io/github/contributors/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/graphs/contributors)`
);
pushBadge(
"issues",
`[![issues](https://img.shields.io/github/issues/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/issues)`,
`[![issues](https://img.shields.io/github/issues/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/issues)`
);
pushBadge(
"pulls",
`[![pull requests](https://img.shields.io/github/issues-pr/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/pulls)`,
`[![pull requests](https://img.shields.io/github/issues-pr/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/pulls)`
);
pushBadge(
"repoSize",
`[![repo size](https://img.shields.io/github/repo-size/${owner}/${repoName}${style})](https://github.com/${ownerRepo})`,
`[![repo size](https://img.shields.io/github/repo-size/${owner}/${repoName}${style})](https://github.com/${ownerRepo})`
);
pushBadge(
"topLanguage",
`[![top language](https://img.shields.io/github/languages/top/${owner}/${repoName}${style})](https://github.com/${ownerRepo})`,
`[![top language](https://img.shields.io/github/languages/top/${owner}/${repoName}${style})](https://github.com/${ownerRepo})`
);
pushBadge(
"languages",
`[![languages](https://img.shields.io/github/languages/count/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/search?l=)`,
`[![languages](https://img.shields.io/github/languages/count/${owner}/${repoName}${style})](https://github.com/${ownerRepo}/search?l=)`
);
}

Expand Down