plugin to generate a list of contributors
23
stars
104
commits
JavaScript
primary language
Sep 23, 2023
updated
remark plugin to generate a list of contributors.
This package is a unified (remark) plugin that takes a list of
contributors and adds them in a table to a ## Contributors heading.
This project is useful when you’re writing documentation for a project, typically a Node.js package, that has one or more readmes and maybe some other markdown files as well. You want to show who helped build the project by adding their names, websites, and perhaps some more info. This package is useful because it’s automated: you can customize who is added and how that’s formatted. But it won’t be as expressive as writing such sections manually.
This plugin is used in remark-git-contributors.
The difference is that that plugin takes the Git history into account, which
isn’t always needed or correct.
This package is ESM only. In Node.js (version 16+), install with npm:
npm install remark-contributors
In Deno with esm.sh:
import remarkContributors from 'https://esm.sh/remark-contributors@7'
In browsers with esm.sh:
<script type="module">
import remarkContributors from 'https://esm.sh/remark-contributors@7?bundle'
</script>
Say we have the following file example.md in this project:
# Example
Some text.
## Contributors
## License
MIT
…and a module example.js:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
import {read} from 'to-vfile'
const file = await remark()
.use(remarkGfm) // This is needed to add support for tables (a GFM feature).
.use(remarkContributors)
.process(await read('example.md'))
console.log(String(file))
…then running node example.js yields:
# Example
Some text.
## Contributors
| Name | Website |
| ------------------- | --------------------------- |
| **Hugh Kennedy** | <https://hughsk.io> |
| **Titus Wormer** | <https://wooorm.com> |
| **Vincent Weevers** | <https://vincentweevers.nl> |
| **Nick Baugh** | <https://niftylettuce.com> |
## License
MIT
👉 Note: These contributors are inferred from the
package.jsonin this project. Running this example in a different package will yield different results.
This package exports no identifiers.
The default export is remarkContributors.
unified().use(remarkContributors[, options])Generate a list of contributors.
In short, this plugin:
/^contributors$/i or options.headingappendIfMissing is set, injects such a headingoptions (Options, optional)
— configurationTransform (Transformer).
name, url, github, or twitter in
formatters to label them properlyurl will be labelled Website (so that
package.json contributors field is displayed nicely)email are ignored@mentions wrapped in an https:// linkContributorContributor in string form (name <email> (url)) or as object (TypeScript
type).
type Contributor = ContributorObject | string
ContributorObjectContributor with fields (TypeScript type).
type ContributorObject = Record<string, unknown>
FormatFormat a field (TypeScript type).
value (unknown)
— value to formatkey (string)
— name of a field in a contributorcontributor (Contributor)
— whole contributorContent (Array<PhrasingContent> | PhrasingContent | string, optional)
FormatterHow to format a field, in short (TypeScript type).
The values can be:
null or undefined — does nothing;false — shortcut for {exclude: true, label: key}, can be used to
exclude default formatters;true — shortcut for {label: key}, can be used to include default
formatters (like email)string — shortcut for {label: value}Formatter — …or a proper formatter objecttype Formatter = FormatterObject | boolean | string | null | undefined
FormatterObjectHow to format a field (TypeScript type).
exclude (boolean, default: false)
— whether to ignore these fieldsformat (Format, optional)
— How to format the celllabel (string, optional)
— text in the header row that labels the column for this fieldFormattersFormatters for fields (TypeScript type).
type Formatters = Record<string, Formatter>
OptionsConfiguration (TypeScript type).
align (AlignType from mdast, optional)
— alignment to use for all cells in the tableappendIfMissing (boolean, default: false)
— inject the section if there is none;
the default does nothing when the section doesn’t exist so that you have to
choose where and if the section is addedcontributors (Array<Contributor>, default:
contributors in package.json in Node)
— list of contributors to inject;
supports string form (name <email> (url));
throws if no contributors are found or givenformatters (string, optional)
— map of fields found in contributors to formatters;
these given formatters extend the default formatters;
the keys in formatters should correspond directly (case-sensitive) to
keys in contributorsheading (RegExp | string, default: 'contributors')
— heading to look forThe following example shows how contributors can be passed:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
const file = await remark()
.use(remarkGfm)
.use(remarkContributors, {
contributors: [
// String form:
'Jane Doe <jane@doe.com> (https://example.com/jane)',
// Object form, with just a name:
{name: 'John Doe'},
// Some more info:
{name: 'Mona Lisa', url: 'https://github.com/monatheoctocat'}
]
})
.process('## Contributors')
console.log(String(file))
Yields:
## Contributors
| Name | Website |
| ------------- | ----------------------------------- |
| **Jane Doe** | <https://example.com/jane> |
| **John Doe** | |
| **Mona Lisa** | <https://github.com/monatheoctocat> |
By default, unknown fields in contributors will be added to the table:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
const file = await remark()
.use(remarkGfm)
.use(remarkContributors, {
contributors: [
{name: 'Jane Doe', age: 31, topping: 'Mozzarella'},
{name: 'John Doe', age: 29, topping: 'Olive'},
{name: 'Mona Lisa', age: 3, topping: 'Pineapple'}
]
})
.process('## Contributors')
console.log(String(file))
Yields:
## Contributors
| Name | age | topping |
| ------------- | --- | ---------- |
| **Jane Doe** | 31 | Mozzarella |
| **John Doe** | 29 | Olive |
| **Mona Lisa** | 3 | Pineapple |
It’s possible to customize how these new fields are formatted:
@@ -12,7 +12,16 @@ const file = await remark()
{name: 'Jane Doe', age: 31, topping: 'Mozzarella'},
{name: 'John Doe', age: 29, topping: 'Olive'},
{name: 'Mona Lisa', age: 3, topping: 'Pineapple'}
- ]
+ ],
+ formatters: {
+ age: {
+ label: 'Age',
+ format(d) {
+ return {type: 'emphasis', children: [{type: 'text', value: String(d)}]}
+ }
+ },
+ topping: 'Topping'
+ }
})
.process('## Contributors')
Yields:
| Name | Age | Topping |
| ------------- | ---- | ---------- |
| **Jane Doe** | *31* | Mozzarella |
| **John Doe** | *29* | Olive |
| **Mona Lisa** | *3* | Pineapple |
👉 Note: observe that the labels of
AgeandToppingare now cased, and that the age values are now wrapped in emphasis.
This package is fully typed with TypeScript.
It exports the additional types
Contributor,
ContributorObject,
Format,
Formatter,
FormatterObject,
Formatters, and
Options.
Projects maintained by the unified collective are compatible with maintained versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, remark-contributors@^7,
compatible with Node.js 16.
This plugin works with unified version 6+ and remark version 7+.
options.contributors (or contributors in package.json) is used and
injected into the tree when given or found.
Data in those lists is formatted by options.formatters.
If a user has access to either, this could open you up to a
cross-site scripting (XSS) attack.
This may become a problem if the markdown is later transformed to rehype (hast) or opened in an unsafe markdown viewer.
remark-git-contributors
– very similar to this plugin but uses info from Gitremark-collapse
– make a section collapsibleremark-normalize-headings
— make sure there is a single top level heading in a document by adjusting
heading ranks accordinglyremark-behead
— increase or decrease markdown heading ranksremark-toc
— generate a table of contents (TOC)remark-license
— generate a license sectionSee contributing.md in remarkjs/.github for ways
to get started.
See support.md for ways to get help.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
| Name | Website |
|---|---|
| Hugh Kennedy | https://hughsk.io |
| Titus Wormer | https://wooorm.com |
| Vincent Weevers | https://vincentweevers.nl |
| Nick Baugh | https://niftylettuce.com |
JavaScript
100.0%
plugin to generate a list of contributors
23
stars
104
commits
JavaScript
primary language
Sep 23, 2023
updated
remark plugin to generate a list of contributors.
This package is a unified (remark) plugin that takes a list of
contributors and adds them in a table to a ## Contributors heading.
This project is useful when you’re writing documentation for a project, typically a Node.js package, that has one or more readmes and maybe some other markdown files as well. You want to show who helped build the project by adding their names, websites, and perhaps some more info. This package is useful because it’s automated: you can customize who is added and how that’s formatted. But it won’t be as expressive as writing such sections manually.
This plugin is used in remark-git-contributors.
The difference is that that plugin takes the Git history into account, which
isn’t always needed or correct.
This package is ESM only. In Node.js (version 16+), install with npm:
npm install remark-contributors
In Deno with esm.sh:
import remarkContributors from 'https://esm.sh/remark-contributors@7'
In browsers with esm.sh:
<script type="module">
import remarkContributors from 'https://esm.sh/remark-contributors@7?bundle'
</script>
Say we have the following file example.md in this project:
# Example
Some text.
## Contributors
## License
MIT
…and a module example.js:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
import {read} from 'to-vfile'
const file = await remark()
.use(remarkGfm) // This is needed to add support for tables (a GFM feature).
.use(remarkContributors)
.process(await read('example.md'))
console.log(String(file))
…then running node example.js yields:
# Example
Some text.
## Contributors
| Name | Website |
| ------------------- | --------------------------- |
| **Hugh Kennedy** | <https://hughsk.io> |
| **Titus Wormer** | <https://wooorm.com> |
| **Vincent Weevers** | <https://vincentweevers.nl> |
| **Nick Baugh** | <https://niftylettuce.com> |
## License
MIT
👉 Note: These contributors are inferred from the
package.jsonin this project. Running this example in a different package will yield different results.
This package exports no identifiers.
The default export is remarkContributors.
unified().use(remarkContributors[, options])Generate a list of contributors.
In short, this plugin:
/^contributors$/i or options.headingappendIfMissing is set, injects such a headingoptions (Options, optional)
— configurationTransform (Transformer).
name, url, github, or twitter in
formatters to label them properlyurl will be labelled Website (so that
package.json contributors field is displayed nicely)email are ignored@mentions wrapped in an https:// linkContributorContributor in string form (name <email> (url)) or as object (TypeScript
type).
type Contributor = ContributorObject | string
ContributorObjectContributor with fields (TypeScript type).
type ContributorObject = Record<string, unknown>
FormatFormat a field (TypeScript type).
value (unknown)
— value to formatkey (string)
— name of a field in a contributorcontributor (Contributor)
— whole contributorContent (Array<PhrasingContent> | PhrasingContent | string, optional)
FormatterHow to format a field, in short (TypeScript type).
The values can be:
null or undefined — does nothing;false — shortcut for {exclude: true, label: key}, can be used to
exclude default formatters;true — shortcut for {label: key}, can be used to include default
formatters (like email)string — shortcut for {label: value}Formatter — …or a proper formatter objecttype Formatter = FormatterObject | boolean | string | null | undefined
FormatterObjectHow to format a field (TypeScript type).
exclude (boolean, default: false)
— whether to ignore these fieldsformat (Format, optional)
— How to format the celllabel (string, optional)
— text in the header row that labels the column for this fieldFormattersFormatters for fields (TypeScript type).
type Formatters = Record<string, Formatter>
OptionsConfiguration (TypeScript type).
align (AlignType from mdast, optional)
— alignment to use for all cells in the tableappendIfMissing (boolean, default: false)
— inject the section if there is none;
the default does nothing when the section doesn’t exist so that you have to
choose where and if the section is addedcontributors (Array<Contributor>, default:
contributors in package.json in Node)
— list of contributors to inject;
supports string form (name <email> (url));
throws if no contributors are found or givenformatters (string, optional)
— map of fields found in contributors to formatters;
these given formatters extend the default formatters;
the keys in formatters should correspond directly (case-sensitive) to
keys in contributorsheading (RegExp | string, default: 'contributors')
— heading to look forThe following example shows how contributors can be passed:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
const file = await remark()
.use(remarkGfm)
.use(remarkContributors, {
contributors: [
// String form:
'Jane Doe <jane@doe.com> (https://example.com/jane)',
// Object form, with just a name:
{name: 'John Doe'},
// Some more info:
{name: 'Mona Lisa', url: 'https://github.com/monatheoctocat'}
]
})
.process('## Contributors')
console.log(String(file))
Yields:
## Contributors
| Name | Website |
| ------------- | ----------------------------------- |
| **Jane Doe** | <https://example.com/jane> |
| **John Doe** | |
| **Mona Lisa** | <https://github.com/monatheoctocat> |
By default, unknown fields in contributors will be added to the table:
import {remark} from 'remark'
import remarkContributors from 'remark-contributors'
import remarkGfm from 'remark-gfm'
const file = await remark()
.use(remarkGfm)
.use(remarkContributors, {
contributors: [
{name: 'Jane Doe', age: 31, topping: 'Mozzarella'},
{name: 'John Doe', age: 29, topping: 'Olive'},
{name: 'Mona Lisa', age: 3, topping: 'Pineapple'}
]
})
.process('## Contributors')
console.log(String(file))
Yields:
## Contributors
| Name | age | topping |
| ------------- | --- | ---------- |
| **Jane Doe** | 31 | Mozzarella |
| **John Doe** | 29 | Olive |
| **Mona Lisa** | 3 | Pineapple |
It’s possible to customize how these new fields are formatted:
@@ -12,7 +12,16 @@ const file = await remark()
{name: 'Jane Doe', age: 31, topping: 'Mozzarella'},
{name: 'John Doe', age: 29, topping: 'Olive'},
{name: 'Mona Lisa', age: 3, topping: 'Pineapple'}
- ]
+ ],
+ formatters: {
+ age: {
+ label: 'Age',
+ format(d) {
+ return {type: 'emphasis', children: [{type: 'text', value: String(d)}]}
+ }
+ },
+ topping: 'Topping'
+ }
})
.process('## Contributors')
Yields:
| Name | Age | Topping |
| ------------- | ---- | ---------- |
| **Jane Doe** | *31* | Mozzarella |
| **John Doe** | *29* | Olive |
| **Mona Lisa** | *3* | Pineapple |
👉 Note: observe that the labels of
AgeandToppingare now cased, and that the age values are now wrapped in emphasis.
This package is fully typed with TypeScript.
It exports the additional types
Contributor,
ContributorObject,
Format,
Formatter,
FormatterObject,
Formatters, and
Options.
Projects maintained by the unified collective are compatible with maintained versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, remark-contributors@^7,
compatible with Node.js 16.
This plugin works with unified version 6+ and remark version 7+.
options.contributors (or contributors in package.json) is used and
injected into the tree when given or found.
Data in those lists is formatted by options.formatters.
If a user has access to either, this could open you up to a
cross-site scripting (XSS) attack.
This may become a problem if the markdown is later transformed to rehype (hast) or opened in an unsafe markdown viewer.
remark-git-contributors
– very similar to this plugin but uses info from Gitremark-collapse
– make a section collapsibleremark-normalize-headings
— make sure there is a single top level heading in a document by adjusting
heading ranks accordinglyremark-behead
— increase or decrease markdown heading ranksremark-toc
— generate a table of contents (TOC)remark-license
— generate a license sectionSee contributing.md in remarkjs/.github for ways
to get started.
See support.md for ways to get help.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
| Name | Website |
|---|---|
| Hugh Kennedy | https://hughsk.io |
| Titus Wormer | https://wooorm.com |
| Vincent Weevers | https://vincentweevers.nl |
| Nick Baugh | https://niftylettuce.com |
JavaScript
100.0%