{"id":28573656,"url":"https://github.com/remarkjs/remark-contributors","last_synced_at":"2025-06-10T21:19:17.405Z","repository":{"id":46105677,"uuid":"37963171","full_name":"remarkjs/remark-contributors","owner":"remarkjs","description":"plugin to generate a list of contributors","archived":false,"fork":false,"pushed_at":"2023-09-23T16:30:01.000Z","size":160,"stargazers_count":23,"open_issues_count":0,"forks_count":10,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-06-09T05:49:42.893Z","etag":null,"topics":["contributors","markdown","remark","remark-plugin"],"latest_commit_sha":null,"homepage":"https://unifiedjs.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/remarkjs.png","metadata":{"funding":{"github":"unifiedjs","open_collective":"unified"},"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-06-24T04:54:57.000Z","updated_at":"2024-09-30T21:10:20.000Z","dependencies_parsed_at":"2024-06-18T16:45:52.178Z","dependency_job_id":"36868510-4585-4376-aa68-90eefa903b5c","html_url":"https://github.com/remarkjs/remark-contributors","commit_stats":{"total_commits":98,"total_committers":6,"mean_commits":"16.333333333333332","dds":"0.19387755102040816","last_synced_commit":"0553e4438b482296912a8df0afab39ae995dda3c"},"previous_names":["hughsk/mdast-contributors"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Fremark-contributors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Fremark-contributors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Fremark-contributors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Fremark-contributors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remarkjs","download_url":"https://codeload.github.com/remarkjs/remark-contributors/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkjs%2Fremark-contributors/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259152784,"owners_count":22813227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contributors","markdown","remark","remark-plugin"],"created_at":"2025-06-10T21:18:56.883Z","updated_at":"2025-06-10T21:19:17.369Z","avatar_url":"https://github.com/remarkjs.png","language":"JavaScript","funding_links":["https://github.com/sponsors/unifiedjs","https://opencollective.com/unified"],"categories":[],"sub_categories":[],"readme":"# remark-contributors\n\n[![Build][build-badge]][build]\n[![Coverage][coverage-badge]][coverage]\n[![Downloads][downloads-badge]][downloads]\n[![Size][size-badge]][size]\n[![Sponsors][sponsors-badge]][collective]\n[![Backers][backers-badge]][collective]\n[![Chat][chat-badge]][chat]\n\n**[remark][]** plugin to generate a list of contributors.\n\n## Contents\n\n*   [What is this?](#what-is-this)\n*   [When should I use this?](#when-should-i-use-this)\n*   [Install](#install)\n*   [Use](#use)\n*   [API](#api)\n    *   [`unified().use(remarkContributors[, options])`](#unifieduseremarkcontributors-options)\n    *   [`Contributor`](#contributor)\n    *   [`ContributorObject`](#contributorobject)\n    *   [`Format`](#format)\n    *   [`Formatter`](#formatter)\n    *   [`FormatterObject`](#formatterobject)\n    *   [`Formatters`](#formatters)\n    *   [`Options`](#options)\n*   [Examples](#examples)\n    *   [Example: passing contributors](#example-passing-contributors)\n    *   [Example: formatters](#example-formatters)\n*   [Types](#types)\n*   [Compatibility](#compatibility)\n*   [Security](#security)\n*   [Related](#related)\n*   [Contribute](#contribute)\n*   [Contributors](#contributors)\n*   [License](#license)\n\n## What is this?\n\nThis package is a [unified][] ([remark][]) plugin that takes a list of\ncontributors and adds them in a table to a `## Contributors` heading.\n\n## When should I use this?\n\nThis project is useful when you’re writing documentation for a project,\ntypically a Node.js package, that has one or more readmes and maybe some other\nmarkdown files as well.\nYou want to show who helped build the project by adding their names, websites,\nand perhaps some more info.\nThis package is useful because it’s automated: you can customize who is added\nand how that’s formatted.\nBut it won’t be as expressive as writing such sections manually.\n\nThis plugin is used in [`remark-git-contributors`][remark-git-contributors].\nThe difference is that that plugin takes the Git history into account, which\nisn’t always needed or correct.\n\n## Install\n\nThis package is [ESM only][esm].\nIn Node.js (version 16+), install with [npm][]:\n\n```sh\nnpm install remark-contributors\n```\n\nIn Deno with [`esm.sh`][esmsh]:\n\n```js\nimport remarkContributors from 'https://esm.sh/remark-contributors@7'\n```\n\nIn browsers with [`esm.sh`][esmsh]:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import remarkContributors from 'https://esm.sh/remark-contributors@7?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\nSay we have the following file `example.md` in this project:\n\n```markdown\n# Example\n\nSome text.\n\n## Contributors\n\n## License\n\nMIT\n```\n\n…and a module `example.js`:\n\n```js\nimport {remark} from 'remark'\nimport remarkContributors from 'remark-contributors'\nimport remarkGfm from 'remark-gfm'\nimport {read} from 'to-vfile'\n\nconst file = await remark()\n  .use(remarkGfm) // This is needed to add support for tables (a GFM feature).\n  .use(remarkContributors)\n  .process(await read('example.md'))\n\nconsole.log(String(file))\n```\n\n…then running `node example.js` yields:\n\n```markdown\n# Example\n\nSome text.\n\n## Contributors\n\n| Name                | Website                     |\n| ------------------- | --------------------------- |\n| **Hugh Kennedy**    | \u003chttps://hughsk.io\u003e         |\n| **Titus Wormer**    | \u003chttps://wooorm.com\u003e        |\n| **Vincent Weevers** | \u003chttps://vincentweevers.nl\u003e |\n| **Nick Baugh**      | \u003chttps://niftylettuce.com\u003e  |\n\n## License\n\nMIT\n```\n\n\u003e 👉 **Note**: These contributors are inferred from the\n\u003e [`package.json`][file-package-json] in this project.\n\u003e Running this example in a different package will yield different results.\n\n## API\n\nThis package exports no identifiers.\nThe default export is [`remarkContributors`][api-remark-contributors].\n\n### `unified().use(remarkContributors[, options])`\n\nGenerate a list of contributors.\n\nIn short, this plugin:\n\n*   looks for the first heading matching `/^contributors$/i` or `options.heading`\n*   if no heading is found and `appendIfMissing` is set, injects such a heading\n*   if there is a heading, replaces everything in that section with a new table\n\n###### Parameters\n\n*   `options` ([`Options`][api-options], optional)\n    — configuration\n\n###### Returns\n\nTransform ([`Transformer`][unified-transformer]).\n\n##### Notes\n\n*   define fields other than `name`, `url`, `github`, or `twitter` in\n    `formatters` to label them properly\n*   by default, fields named `url` will be labelled `Website` (so that\n    `package.json` contributors field is displayed nicely)\n*   by default, fields named `email` are ignored\n*   name fields are displayed as strong\n*   GitHub and Twitter URLs are automatically stripped and displayed with\n    `@mention`s wrapped in an `https://` link\n*   if a field is undefined for a given contributor, then the value will be an\n    empty table cell\n*   columns are sorted in the order they are defined (first defined means first\n    displayed)\n\n### `Contributor`\n\nContributor in string form (`name \u003cemail\u003e (url)`) or as object (TypeScript\ntype).\n\n###### Type\n\n```ts\ntype Contributor = ContributorObject | string\n```\n\n### `ContributorObject`\n\nContributor with fields (TypeScript type).\n\n###### Type\n\n```ts\ntype ContributorObject = Record\u003cstring, unknown\u003e\n```\n\n### `Format`\n\nFormat a field (TypeScript type).\n\n###### Parameters\n\n*   `value` (`unknown`)\n    — value to format\n*   `key` (`string`)\n    — name of a field in a contributor\n*   `contributor` ([`Contributor`][api-contributor])\n    — whole contributor\n\n###### Returns\n\nContent (`Array\u003cPhrasingContent\u003e | PhrasingContent | string`, optional)\n\n### `Formatter`\n\nHow to format a field, in short (TypeScript type).\n\nThe values can be:\n\n*   `null` or `undefined` — does nothing;\n*   `false` — shortcut for `{exclude: true, label: key}`, can be used to\n    exclude default formatters;\n*   `true` — shortcut for `{label: key}`, can be used to include default\n    formatters (like `email`)\n*   `string` — shortcut for `{label: value}`\n*   `Formatter` — …or a proper formatter object\n\n###### Type\n\n```ts\ntype Formatter = FormatterObject | boolean | string | null | undefined\n```\n\n### `FormatterObject`\n\nHow to format a field (TypeScript type).\n\n###### Fields\n\n*   `exclude` (`boolean`, default: `false`)\n    — whether to ignore these fields\n*   `format` ([`Format`][api-format], optional)\n    — How to format the cell\n*   `label` (`string`, optional)\n    — text in the header row that labels the column for this field\n\n### `Formatters`\n\nFormatters for fields (TypeScript type).\n\n###### Type\n\n```ts\ntype Formatters = Record\u003cstring, Formatter\u003e\n```\n\n### `Options`\n\nConfiguration (TypeScript type).\n\n###### Fields\n\n*   `align` ([`AlignType` from `mdast`][mdast-align-type], optional)\n    — alignment to use for all cells in the table\n*   `appendIfMissing` (`boolean`, default: `false`)\n    — inject the section if there is none;\n    the default does nothing when the section doesn’t exist so that you have to\n    choose where and if the section is added\n*   `contributors` ([`Array\u003cContributor\u003e`][api-contributor], default:\n    contributors in `package.json` in Node)\n    — list of contributors to inject;\n    supports string form (`name \u003cemail\u003e (url)`);\n    throws if no contributors are found or given\n*   `formatters` (`string`, optional)\n    — map of fields found in `contributors` to formatters;\n    these given formatters extend the [default formatters][file-formatters];\n    the keys in `formatters` should correspond directly (case-sensitive) to\n    keys in `contributors`\n*   `heading` (`RegExp | string`, default: `'contributors'`)\n    — heading to look for\n\n## Examples\n\n### Example: passing contributors\n\nThe following example shows how contributors can be passed:\n\n```js\nimport {remark} from 'remark'\nimport remarkContributors from 'remark-contributors'\nimport remarkGfm from 'remark-gfm'\n\nconst file = await remark()\n  .use(remarkGfm)\n  .use(remarkContributors, {\n    contributors: [\n      // String form:\n      'Jane Doe \u003cjane@doe.com\u003e (https://example.com/jane)',\n      // Object form, with just a name:\n      {name: 'John Doe'},\n      // Some more info:\n      {name: 'Mona Lisa', url: 'https://github.com/monatheoctocat'}\n    ]\n  })\n  .process('## Contributors')\n\nconsole.log(String(file))\n```\n\nYields:\n\n```markdown\n## Contributors\n\n| Name          | Website                             |\n| ------------- | ----------------------------------- |\n| **Jane Doe**  | \u003chttps://example.com/jane\u003e          |\n| **John Doe**  |                                     |\n| **Mona Lisa** | \u003chttps://github.com/monatheoctocat\u003e |\n```\n\n### Example: formatters\n\nBy default, unknown fields in contributors will be added to the table:\n\n```js\nimport {remark} from 'remark'\nimport remarkContributors from 'remark-contributors'\nimport remarkGfm from 'remark-gfm'\n\nconst file = await remark()\n  .use(remarkGfm)\n  .use(remarkContributors, {\n    contributors: [\n      {name: 'Jane Doe', age: 31, topping: 'Mozzarella'},\n      {name: 'John Doe', age: 29, topping: 'Olive'},\n      {name: 'Mona Lisa', age: 3, topping: 'Pineapple'}\n    ]\n  })\n  .process('## Contributors')\n\nconsole.log(String(file))\n```\n\nYields:\n\n```markdown\n## Contributors\n\n| Name          | age | topping    |\n| ------------- | --- | ---------- |\n| **Jane Doe**  | 31  | Mozzarella |\n| **John Doe**  | 29  | Olive      |\n| **Mona Lisa** | 3   | Pineapple  |\n```\n\nIt’s possible to customize how these new fields are formatted:\n\n```diff\n@@ -12,7 +12,16 @@ const file = await remark()\n       {name: 'Jane Doe', age: 31, topping: 'Mozzarella'},\n       {name: 'John Doe', age: 29, topping: 'Olive'},\n       {name: 'Mona Lisa', age: 3, topping: 'Pineapple'}\n-    ]\n+    ],\n+    formatters: {\n+      age: {\n+        label: 'Age',\n+        format(d) {\n+          return {type: 'emphasis', children: [{type: 'text', value: String(d)}]}\n+        }\n+      },\n+      topping: 'Topping'\n+    }\n   })\n   .process('## Contributors')\n```\n\nYields:\n\n```markdown\n| Name          | Age  | Topping    |\n| ------------- | ---- | ---------- |\n| **Jane Doe**  | *31* | Mozzarella |\n| **John Doe**  | *29* | Olive      |\n| **Mona Lisa** | *3*  | Pineapple  |\n```\n\n\u003e 👉 **Note**: observe that the labels of `Age` and `Topping` are now cased,\n\u003e and that the age values are now wrapped in emphasis.\n\n## Types\n\nThis package is fully typed with [TypeScript][].\nIt exports the additional types\n[`Contributor`][api-contributor],\n[`ContributorObject`][api-contributor-object],\n[`Format`][api-format],\n[`Formatter`][api-formatter],\n[`FormatterObject`][api-formatter-object],\n[`Formatters`][api-formatters], and\n[`Options`][api-options].\n\n## Compatibility\n\nProjects maintained by the unified collective are compatible with maintained\nversions of Node.js.\n\nWhen we cut a new major release, we drop support for unmaintained versions of\nNode.\nThis means we try to keep the current release line, `remark-contributors@^7`,\ncompatible with Node.js 16.\n\nThis plugin works with `unified` version 6+ and `remark` version 7+.\n\n## Security\n\n`options.contributors` (or `contributors` in `package.json`) is used and\ninjected into the tree when given or found.\nData in those lists is formatted by `options.formatters`.\nIf a user has access to either, this could open you up to a\n[cross-site scripting (XSS)][wiki-xss] attack.\n\nThis may become a problem if the markdown is later transformed to\n**[rehype][]** (**[hast][]**) or opened in an unsafe markdown viewer.\n\n## Related\n\n*   [`remark-git-contributors`][remark-git-contributors]\n    – very similar to this plugin but uses info from Git\n*   [`remark-collapse`](https://github.com/Rokt33r/remark-collapse)\n    – make a section collapsible\n*   [`remark-normalize-headings`](https://github.com/remarkjs/remark-normalize-headings)\n    — make sure there is a single top level heading in a document by adjusting\n    heading ranks accordingly\n*   [`remark-behead`](https://github.com/mrzmmr/remark-behead)\n    — increase or decrease markdown heading ranks\n*   [`remark-toc`](https://github.com/remarkjs/remark-toc)\n    — generate a table of contents (TOC)\n*   [`remark-license`](https://github.com/remarkjs/remark-license)\n    — generate a license section\n\n## Contribute\n\nSee [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways\nto get started.\nSee [`support.md`][support] for ways to get help.\n\nThis project has a [code of conduct][coc].\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.\n\n## Contributors\n\n| Name                | Website                     |\n| ------------------- | --------------------------- |\n| **Hugh Kennedy**    | \u003chttps://hughsk.io\u003e         |\n| **Titus Wormer**    | \u003chttps://wooorm.com\u003e        |\n| **Vincent Weevers** | \u003chttps://vincentweevers.nl\u003e |\n| **Nick Baugh**      | \u003chttps://niftylettuce.com\u003e  |\n\n## License\n\n[MIT][license] © [Hugh Kennedy][author]\n\n\u003c!-- Definitions --\u003e\n\n[build-badge]: https://github.com/remarkjs/remark-contributors/workflows/main/badge.svg\n\n[build]: https://github.com/remarkjs/remark-contributors/actions\n\n[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-contributors.svg\n\n[coverage]: https://codecov.io/github/remarkjs/remark-contributors\n\n[downloads-badge]: https://img.shields.io/npm/dm/remark-contributors.svg\n\n[downloads]: https://www.npmjs.com/package/remark-contributors\n\n[size-badge]: https://img.shields.io/bundlejs/size/remark-contributors\n\n[size]: https://bundlejs.com/?q=remark-contributors\n\n[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg\n\n[backers-badge]: https://opencollective.com/unified/backers/badge.svg\n\n[collective]: https://opencollective.com/unified\n\n[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg\n\n[chat]: https://github.com/remarkjs/remark/discussions\n\n[npm]: https://docs.npmjs.com/cli/install\n\n[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[esmsh]: https://esm.sh\n\n[health]: https://github.com/remarkjs/.github\n\n[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md\n\n[support]: https://github.com/remarkjs/.github/blob/main/support.md\n\n[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md\n\n[license]: license\n\n[author]: https://hughsk.io\n\n[hast]: https://github.com/syntax-tree/hast\n\n[mdast-align-type]: https://github.com/syntax-tree#aligntype\n\n[rehype]: https://github.com/rehypejs/rehype\n\n[remark]: https://github.com/remarkjs/remark\n\n[remark-git-contributors]: https://github.com/remarkjs/remark-git-contributors\n\n[typescript]: https://www.typescriptlang.org\n\n[unified]: https://github.com/unifiedjs/unified\n\n[unified-transformer]: https://github.com/unifiedjs/unified#transformer\n\n[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting\n\n[file-formatters]: lib/formatters.js\n\n[file-package-json]: package.json\n\n[api-contributor]: #contributor\n\n[api-contributor-object]: #contributorobject\n\n[api-format]: #format\n\n[api-formatter]: #formatter\n\n[api-formatter-object]: #formatterobject\n\n[api-formatters]: #formatters\n\n[api-options]: #options\n\n[api-remark-contributors]: #unifieduseremarkcontributors-options\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkjs%2Fremark-contributors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremarkjs%2Fremark-contributors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkjs%2Fremark-contributors/lists"}