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

markdown-patch

v1.0.0

Published

Change markdown documents by inserting or changing content relative to headings or other parts of a document's structure.

Downloads

839

Readme

markdown-patch

Make targeted, structure-aware edits to Markdown documents — without sed.

Instead of treating a document as a blob of text, markdown-patch understands its structure (headings, block references, frontmatter) and lets you append, prepend, or replace content at a specific location within it.

Available as both a CLI tool (mdpatch) and a TypeScript/JavaScript library.

API docs: https://coddingtonbear.github.io/markdown-patch/

Install

npm install markdown-patch

The mdpatch binary is included and available after install.

Quick start

Given a document notes.md:

---
status: in-progress
---

# Meeting Notes

## Action Items

- Follow up with design team

Append a new item under Action Items:

echo "- Send the report" | mdpatch patch append heading "Meeting Notes::Action Items" notes.md

Replace the status frontmatter field:

echo '"done"' | mdpatch patch replace frontmatter status notes.md

Not sure what targets exist in a document? Use print-map:

mdpatch print-map notes.md

CLI reference

mdpatch patch

Apply a single patch operation.

mdpatch patch [options] <operation> <targetType> <target> <documentPath>
  • <operation>append, prepend, or replace
  • <targetType>heading, block, or frontmatter
  • <target> — the target address (see below)
  • <documentPath> — file to modify (patched in-place by default)

Options:

| Flag | Description | |---|---| | -i, --input <path> | Read content from a file instead of stdin | | -o, --output <path> | Write result to a file instead of patching in-place; use - for stdout | | -d, --delimiter <str> | Heading path delimiter (default: ::) |

mdpatch apply

Apply one or more patch instructions from a JSON patch file.

mdpatch apply [options] <documentPath> <patchFile>

The patch file should be a JSON object (single instruction) or JSON array (multiple instructions). Use - to read from stdin.

mdpatch query

Extract the content of a specific target and write it to stdout (or a file).

mdpatch query [options] <targetType> <target> <documentPath>

mdpatch print-map

Show all patchable targets discovered in a document, useful for finding the right target address.

mdpatch print-map <documentPath> [regex]

Targets

Headings

Address a section by its heading path, delimited by :: (or a custom delimiter). Nested headings use the full path:

# Target the top-level "Overview" section
mdpatch patch append heading "Overview" notes.md

# Target a nested heading
mdpatch patch append heading "Meeting Notes::Action Items" notes.md

Block references

Address a paragraph, table, or other block by its Obsidian block ID (e.g. ^abc123):

echo "New row content" | mdpatch patch append block "abc123" notes.md

When the target block is a Markdown table and content type is application/json, rows can be appended or prepended as JSON arrays.

Frontmatter fields

Address a YAML frontmatter key by name. Content is treated as JSON:

# Set a scalar
echo '"done"' | mdpatch patch replace frontmatter status notes.md

# Append to a list
echo '"new-tag"' | mdpatch patch append frontmatter tags notes.md

Library usage

import { applyPatch, getDocumentMap } from "markdown-patch";

const document = `# My Note\n\n## Tasks\n\n- Buy milk\n`;

const patched = applyPatch(document, {
  operation: "append",
  targetType: "heading",
  target: ["My Note", "Tasks"],
  content: "- Write tests\n",
});

getDocumentMap parses a document and returns its structure — useful for inspecting what headings, blocks, and frontmatter fields are available before patching.

Patch instruction options

| Option | Type | Description | |---|---|---| | operation | "append" \| "prepend" \| "replace" | What to do | | targetType | "heading" \| "block" \| "frontmatter" | What to target | | target | string \| string[] | Target address (array for heading paths) | | content | string | Content to apply | | contentType | "text/markdown" \| "application/json" | Defaults to text/markdown | | targetScope | "content" \| "marker" \| "markerAndContent" | Heading and block only. Defaults to "content". "marker" targets only the heading line or block ID (useful for renaming). "markerAndContent" targets the full range covering both. | | createTargetIfMissing | boolean | Create the heading or block if it doesn't exist | | rejectIfContentPreexists | boolean | Reject the patch (with ContentAlreadyPreexistsInTarget) if the supplied content is already present in the target. Ignored for replace operations. | | trimTargetWhitespace | boolean | Trim whitespace from the target boundary before joining |