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 🙏

© 2026 – Pkg Stats / Ryan Hefner

code-divider

v1.1.0

Published

Turn region/section labels into centered, fixed-width comment headers. Any language, any editor.

Readme

code-divider

NPM Version NPM Downloads License CI

code-divider turns simple comment markers into tidy, centered region/section dividers. No counting = signs. No lining things up by hand.

Use it from the command line, run it automatically when you save, or call it from your own code.

👀 Preview

code-divider inserting two region headers and a section header

🧭 Table of contents

🚀 Quick start

Add a marker on its own line in a source file:

// @reg utilities

// @sec helper functions

Then run (inside of your project folder):

npx code-divider

Your markers are replaced in place with formatted headers. That’s it!

Run it again after changing a setting such as the character limit and the headers it generated earlier are re-centered to match.

You can target a file or a folder. Folders are searched recursively.

npx code-divider --path ./src --dry-run

📌 Markers

There are two kinds of dividers:

| Marker | Creates | | --- | --- | | // @reg Label | A three-line boxed region header. | | // @sec Label | A single-line section header. |

Use your language’s comment syntax:

// @sec helper functions
# @sec helper functions
/* @sec helper functions */

By default, region labels become UPPERCASE and section labels become Capitalized Words. You can customize both in Configuration.

Built-in support includes JavaScript, TypeScript, Java, CSS, SCSS, C, C++, Go, Rust, PHP, Ruby, Python, Bash, and SQL. You can add more languages through the configuration file.

💻 Command-line options

npx code-divider [options]

With no options, code-divider processes the current directory.

| Option | What it does | | --- | --- | | -p, --path <path> | Process a file or directory. Defaults to the current directory. | | -c, --config <file> | Use a specific config file. Its settings override the built-in defaults. | | -d, --dry-run | List the files that would change without writing anything. | | --check | Like --dry-run, but exit with code 1 if any file would change. Useful for CI and pre-commit hooks. | | -i, --init [dir] | Create a default code-divider.config.json in the given directory, or the current directory if omitted. Runs on its own without processing source files. | | -h, --help | Show help. | | -v, --version | Show the version. |

A few examples:

# Process the current directory
npx code-divider

# Process one file
npx code-divider --path ./src/index.ts

# Check for changes in CI without modifying files
npx code-divider --check

# Use a specific config file
npx code-divider --config ./custom.config.json

💾 Run on save

This is my favorite way to use code-divider: write a marker, hit save, and let your editor handle the rest.

If your editor supports running commands on save, configure it to run npx code-divider.

For VS Code, install the Run on Save extension and add this setting to your settings.json:

{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "\\.(css|js|jsx|ts|tsx)$",
        "cmd": "npx code-divider"
      }
    ]
  }
}

🤔 Why not snippets?

Editor snippets can insert a header template, and if they work for you, great! What they can't do is measure the label. Snippet transforms can change case, but they can't count characters, so the filler stays the same length and the line grows with the label:

// ================================= Helpers ================================= //
// ================================= Shared Helpers ================================= //

code-divider sizes the filler around each label, so every header ends at the same column:

// ================================ Helpers ================================ //
// ============================= Shared Helpers ============================ //

| | Snippets | code-divider | | --- | --- | --- | | Centers the label at a fixed width | No | Yes | | Appears as you type | Yes | On save, with Run on save | | Works in any editor | One format per editor | Yes | | Covers every language | One entry per language | One config file | | Can be enforced in CI | No | Yes, with --check |

🧩 Divider anatomy

Here’s a section divider, shortened for readability:

// ============== My Section ============== //

Dividers are recognized on later runs by their bookends and filler character, so changing CharacterLimit or a label format and running code-divider again updates headers that were generated earlier.

These are the names used throughout the configuration:

| Term | Meaning | | --- | --- | | Marker | The token that requests a divider: @reg or @sec. | | Comment | The comment syntax used to write the marker, such as //, #, or /* ... */. | | Label | The title after the marker, such as My Section. | | Filler character | The repeated character that fills the available space: = in this example. | | Bookends | The strings at the start and end of each generated line: "// " and " //" here. |

🔧 Configuration

The defaults work out of the box. Add a config file only when you want to make the dividers your own.

Create a config file

Start with a file containing all the default settings:

npx code-divider --init

This creates code-divider.config.json in the current directory. It won’t overwrite an existing file.

The file starts with a $schema line pointing at the package's JSON schema, so editors such as VS Code can autocomplete settings and flag typos. If you write the file by hand, add the line yourself:

{
  "$schema": "https://unpkg.com/code-divider@1/schema.json"
}

To create it somewhere else:

npx code-divider --init ./packages/app

How config files are found

Unless you pass --config <file>, code-divider checks locations in this order:

  1. The target directory, or the containing directory if the target is a file.
  2. The directory the command is run from.

The first config file found wins. These config files are not merged together.

Settings in the selected config file override the built-in defaults. Anything you leave out keeps its default value. If no config is found, the built-in defaults are used.

Shared settings

The All key contains settings shared by every language:

| Setting | What it controls | Default | | --- | --- | --- | | CharacterLimit | The column that generated header lines extend to. | 79 | | FillerCharacter | The character used to fill the header lines. | "=" | | RegionLabelFormat | How region labels are capitalized. | "uppercase" | | SectionLabelFormat | How section labels are capitalized. | "capitalize" |

Both label-format settings accept:

| Value | Example | | --- | --- | | "uppercase" | my cool section → MY COOL SECTION | | "lowercase" | My Cool Section → my cool section | | "capitalize" | my COOL section → My Cool Section | | "none" | Leave the label exactly as written. |

Words that start or end with a non-alphanumeric character are left unchanged under every format. That keeps labels containing things like @decorator or .foo intact.

Language-specific settings

Other than All and filter, top-level config keys can be any string value, they're just there for organization. You can use a built-in key to customize that language's current settings, or a new key to add your own. Set a built-in key to null to remove that language. Keys starting with $ (such as $schema) are ignored.

| Setting | What it controls | | --- | --- | | Extensions | File extensions to match, without the leading dot. For example, ["py"]. | | Comment | A [start, end] pair describing the comment syntax used for markers. Use "" as the end for line comments. | | Bookends | Optional [start, end] strings for generated header lines. Defaults to Comment; for line comments, the opener is mirrored on the right. For example, "# " becomes ["# ", " #"]. | | CharacterLimit | Override All.CharacterLimit for this language. Note that this DOES account for indentation. So the divider will stop at the value regardless of where the marker starts. | | FillerCharacter | Override All.FillerCharacter for this language. | | RegionLabelFormat | Override All.RegionLabelFormat for this language. | | SectionLabelFormat | Override All.SectionLabelFormat for this language. |

For example:

{
  "All": {
    "CharacterLimit": 100,
    "FillerCharacter": "-"
  },
  "Java": {
    "Bookends": ["// ", " //"]
  },
  "Python": {
    "Extensions": ["py"],
    "Comment": ["# ", ""]
  },
  "Sql": null
}
// Main.java
class Main {

    // ===================================================================== //
    //                               FUNCTIONS                               //
    // ===================================================================== //

    public static void main(String[] args) {
        System.out.println("Hello code-dividers");
    }
}
# Main.python

# =========================================================================== #
#                                  CONSTANTS                                  #
# =========================================================================== #

print('Hello code-divider')

Default Settings

These are the language keys, file extensions, and comment styles available by default.

Extensions are matched case-insensitively, so Main.TS is treated like main.ts.

| Config key | File extensions | Marker example | Generated bookends | | --- | --- | --- | --- | | JavaScript | .js .jsx .ts .tsx .mjs .cjs | // @reg Label | "// " … " //" | | Java | .java | // @reg Label | "// " … " //" | | Css | .css .scss | /* @reg Label */ | "/* " … " */" | | C | .c .h | // @reg Label | "// " … " //" | | Cpp | .cpp .cc .cxx .hpp .hh .hxx | // @reg Label | "// " … " //" | | Go | .go | // @reg Label | "// " … " //" | | Rust | .rs | // @reg Label | "// " … " //" | | Php | .php | // @reg Label | "// " … " //" | | Ruby | .rb | # @reg Label | "# " … " #" | | Python | .py .pyi .pyw | # @reg Label | "# " … " #" | | Bash | .sh | # @reg Label | "# " … " #" | | Sql | .sql | -- @reg Label | "-- " … " --" |

Filtering files

Use the top-level filter key to choose which files get processed.

Patterns work like include and exclude in a tsconfig.json. They are relative to the folder being processed.

| Setting | What it does | | --- | --- | | include | Process only matching files. Defaults to [], which uses the default recursive search. | | exclude | Skip matching files and folders. Your list replaces the built-in exclusions. Use [] to exclude nothing. |

Filters select the files to consider, but to be updated those files still need to match a configured language extension.

Symbolic links are skipped while walking a directory, whether they point at a file or a folder, so code-divider never edits anything outside the folder you gave it. A symlink passed directly with --path is followed.

In case you're wondering why I didn't use Node's built-in fs.glob function, it's only available in Node 22+ and marked experimental until Node 24.

Default exclusions

Out of the box, code-divider skips:

  • At any depth: node_modules, .vscode, .idea, .claude, and files ending in .log or .json.
  • At the top level: bin, lib, and dist.

💻 Programmatic use

import { insertCodeDividers } from 'code-divider';

const updatedFiles = await insertCodeDividers(targetPath?, options?)

targetPath can be a file or directory. Relative paths are resolved against options.cwd, and an empty or omitted path means options.cwd itself.

All options are optional:

| Option | What it does | Default | | --- | --- | --- | | cwd | Base directory for resolving relative paths. | process.cwd() | | configFilePath | Use a specific config file. If empty, check the target directory, then cwd, then use the built-in defaults. | '' | | config | An inline config object with the same shape as a config file. Replaces the config-file lookup entirely; cannot be combined with configFilePath. The CodeDividerConfig type describes it. | none | | isDryRun | Return the files that would change without writing them. | false | | logger | Handle messages with an object exposing info and warn methods, such as console. | Console output | | silent | Suppress all messages. Takes priority over logger. | false |

The logger receives:

  • info messages, such as which config file is being used.
  • warn messages, such as a marker with no label.

For example, with an inline config:

import { insertCodeDividers, type CodeDividerConfig } from 'code-divider';

const config: CodeDividerConfig = {
  All: { CharacterLimit: 100 },
  JavaScript: null, // don't touch JS/TS files
};

const updatedFiles = await insertCodeDividers('src', { config, isDryRun: true });

📄 License

MIT © seanpmaxwell