npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

remark-capitalize-headings

v2.0.1

Published

remark plugin that selectively transforms headings using vercel's title package

Downloads

332

Readme

Black Lives Matter! Last commit timestamp Codecov Source license Monthly Downloads NPM version Uses Semantic Release!

remark-capitalize-headings

This is a unified (remark) plugin that selectively transforms headings using vercel's title package, which adheres to The Chicago Manual of Style. Comes with full unicode support (reducible to title's unicode support) too.

While you can get a similar effect by using remark-capitalize (this plugin's abandoned? inspiration), remark-capitalize-headings comes with the following changes:

The end result is a less bothersome experience, where you're more likely to use a single simple configuration across your projects without constant tweaking.

You might also be interested in remark-ignore, which lets you instruct remark not to transform parts of your Markdown documents. It can be used as a last resort to ignore individual headers when this plugin's options just will not do.


Install

Due to the nature of the unified ecosystem, this package is ESM only and cannot be require'd.

npm install --save-dev remark-capitalize-headings

Usage

Via API

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings)
  .process(await read('example.md'));

console.log(String(file));

Via remark-cli

remark -o --use capitalize-headings README.md

Via unified configuration

In package.json:

  /* … */
  "remarkConfig": {
    "plugins": [
      "remark-capitalize-headings"
      /* … */
    ]
  },
  /* … */

In .remarkrc.js:

module.exports = {
  plugins: [
    // …
    'capitalize-headings'
  ]
};

In .remarkrc.mjs:

import remarkCapitalizeHeadings from 'remark-capitalize-headings';

export default {
  plugins: [
    // …
    remarkCapitalizeHeadings
  ]
};

API

Detailed interface information can be found under docs/.

Options

All "RegExp" values below are assumed to be strings, and will be transformed into regular expression objects via the following expression: RegExp(value, 'gu').

This plugin recognizes the following options:

excludeHeadingLevel

Valid values: { [level: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"]: boolean }
Default: {}

Headings of the specified level in { [level]: true } will be excluded from capitalization entirely, where h1 corresponds to <h1>…</h1>/# …, h2 to <h2>…</h2>/## …, etc.

Excludes with false values are treated as if they were commented out.

excludeSectionRegExp

Valid values: [RegExp]
Default: []

Entire sections with a stringified heading matching at least one of the given regular expression strings will be excluded from capitalization entirely.

replaceHeadingRegExp

Valid values: { [regExp: RegExp]: string }
Default: { "(?<=\\s)a(?=\\p{P})": "A" }

This option lets you manipulate non-excluded headers in their stringified form after they've been transformed by title. This extra context is useful for tasks like capitalizing a word only if it appears at the end of a heading, or as part of a phrase, or to prevent a word from being capitalized. This option also supports using matching groups during replacement.

The only limitation is that any manipulations must not change the length of the (stringified) header. If they do, an error will be thrown. Since this plugin is meant for capitalization, there isn't much reason to add or remove characters anyway.

By default, a is replaced with A when it appears alone before a single punctuation character; e.g., # Section a: Raised By Wolves becomes # Section A: Raised By Wolves. This diverges from title's default behavior at time of writing but is compliant with the CMOS.

For example: in the title # Evaluating the Notation of the Associated Press and the Style of the New York Times, you may want to capitalize the the that occurs before Associated Press and before New York Times, but not anywhere else. This could be achieved with the following:

{
  replaceHeadingRegExp: {
    'the Associated Press': 'The Associated Press',
    'the New York Times': 'The New York Times',
  }
}

Which would yield: # Evaluating the Notation of The Associated Press and the Style of The New York Times.

Examples

Suppose we have the following Markdown file example.md:

# my documentation

## Section 1 is [the best](https://google.com)

### Subsection a

### Subsection _a_

### Subsection \_a

### Subsection a: be see

### Subsection b

### Subsection C

## section 2 is the test

### subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

#### Additional option: `options.opt3`

## Section 3 has the rest {#section-three}

### Subsection [a][1]

#### Sci-fi title generator

##### children of celeste

##### the bionic oblivion

##### snows Of arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Using the Default Configuration

Running the following JavaScript:

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings)
  .process(await read('example.md'));

console.log(String(file));

Would output the following compared to example.md:

-# my documentation
+# My Documentation

-## Section 1 is [the best](https://google.com)
+## Section 1 Is [the best](https://google.com)

-### Subsection a
+### Subsection A

-### Subsection _a_
+### Subsection _A_

### Subsection \_a

-### Subsection a: be see
+### Subsection A: Be See

-### Subsection b
+### Subsection B

### Subsection C

-## section 2 is the test
+## Section 2 Is the Test

-### subsection 1
+### Subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

-#### Additional option: `options.opt3`
+#### Additional Option: `options.opt3`

-## Section 3 has the rest {#section-three}
+## Section 3 Has the Rest {#section-Three}

### Subsection [a][1]

-#### Sci-fi title generator
+#### Sci-Fi Title Generator

-##### children of celeste
+##### Children of Celeste

-##### the bionic oblivion
+##### The Bionic Oblivion

-##### snows Of arrakis
+##### Snows of Arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Using excludeHeadingLevel

Running the following JavaScript:

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings, {
    // Do not capitalize any H3 and H4 headings
    excludeHeadingLevel: { h3: true, h4: true }
  })
  .process(await read('example.md'));

console.log(String(file));

Would output the following compared to example.md:

-# my documentation
+# My Documentation

-## Section 1 is [the best](https://google.com)
+## Section 1 Is [the best](https://google.com)

### Subsection a

### Subsection _a_

### Subsection \_a

### Subsection a: be see

### Subsection b

### Subsection C

-## section 2 is the test
+## Section 2 Is the Test

### subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

#### Additional option: `options.opt3`

-## Section 3 has the rest {#section-three}
+## Section 3 Has the Rest {#section-Three}

### Subsection [a][1]

#### Sci-fi title generator

-##### children of celeste
+##### Children of Celeste

-##### the bionic oblivion
+##### The Bionic Oblivion

-##### snows Of arrakis
+##### Snows of Arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Using excludeHeadingText

Running the following JavaScript:

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings, {
    // Don't mess with {#custom-headers} from remark-heading-id
    // See: https://github.com/Xunnamius/unified-utils/issues/95
    excludeHeadingText: ['\\{\\s*#.*?\\}\\s*$']
  })
  .process(await read('example.md'));

console.log(String(file));

Would output the following compared to example.md:

-# my documentation
+# My Documentation

-## Section 1 is [the best](https://google.com)
+## Section 1 Is [the best](https://google.com)

### Subsection a

### Subsection _a_

### Subsection \_a

### Subsection a: be see

### Subsection b

### Subsection C

-## section 2 is the test
+## Section 2 Is the Test

### subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

#### Additional option: `options.opt3`

-## Section 3 has the rest {#section-three}
+## Section 3 Has the Rest {#section-three}

### Subsection [a][1]

#### Sci-fi title generator

-##### children of celeste
+##### Children of Celeste

-##### the bionic oblivion
+##### The Bionic Oblivion

-##### snows Of arrakis
+##### Snows of Arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Using excludeSectionRegExp

Running the following JavaScript:

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings, {
    // Do not capitalize headings with "subsection" in their text, nor any of the
    // headings below them
    excludeSectionRegExp: ['(s|S)ubsection']
  })
  .process(await read('example.md'));

console.log(String(file));

Would output the following compared to example.md:

-# my documentation
+# My Documentation

-## Section 1 is [the best](https://google.com)
+## Section 1 Is [the best](https://google.com)

### Subsection a

### Subsection _a_

### Subsection \_a

### Subsection a: be see

### Subsection b

### Subsection C

-## section 2 is the test
+## Section 2 Is the Test

### subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

#### Additional option: `options.opt3`

-## Section 3 has the rest {#section-three}
+## Section 3 Has the Rest {#section-Three}

### Subsection [a][1]

#### Sci-fi title generator

##### children of celeste

##### the bionic oblivion

##### snows Of arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Using replaceHeadingRegExp

Running the following JavaScript:

import { read } from 'to-vfile';
import { remark } from 'remark';
import remarkCapitalizeHeadings from 'remark-capitalize-headings';

const file = await remark()
  .use(remarkCapitalizeHeadings, {
    // Make some last-minute adjustments
    replaceHeadingRegExp: {
      '\\s(_?)(a|A)$': ' $1Y',
      'Has the Rest': 'Has The Rest'
    }
  })
  .process(await read('example.md'));

console.log(String(file));

Would output the following compared to example.md:

-# my documentation
+# My Documentation

-## Section 1 is [the best](https://google.com)
+## Section 1 Is [the best](https://google.com)

-### Subsection a
+### Subsection Y

-### Subsection _a_
+### Subsection _Y_

-### Subsection \_a
+### Subsection \_Y

-### Subsection a: be see
+### Subsection a: Be See

-### Subsection b
+### Subsection B

### Subsection C

-## section 2 is the test
+## Section 2 Is the Test

-### subsection 1
+### Subsection 1

### Subsection 2

#### `options.opt1`

#### `options.opt2`

-#### Additional option: `options.opt3`
+#### Additional Option: `options.opt3`

-## Section 3 has the rest {#section-three}
+## Section 3 Has The Rest {#section-Three}

### Subsection [a][1]

-#### Sci-fi title generator
+#### Sci-Fi Title Generator

-##### children of celeste
+##### Children of Celeste

-##### the bionic oblivion
+##### The Bionic Oblivion

-##### snows Of arrakis
+##### Snows of Arrakis

[1]: https://www.youtube.com/watch?v=dFs4yX4V7NQ

Related

Contributing and Support

New issues and pull requests are always welcome and greatly appreciated! 🤩 Just as well, you can star 🌟 this project to let me know you found it useful! ✊🏿 Thank you!

See CONTRIBUTING.md and SUPPORT.md for more information.

Contributors

See the table of contributors.