1.1.0 • Public • Published


Build & Publish to NPM and GHP


Takes in a list of markdown files and merges them into a single output file with optional HTML and PDF output. Other advantages:

  • Merge all md files in a folder
  • auto-resolution of all relative links in files for assets, other markdown files no matter their location locally
  • built in link checker of final file
  • Use a Manifest file (json/yaml):
    • Specify the input list of files (relative or absolute)
    • Specify the output file (relative or absolute)
      • Add pandoc arguments for HTML output
      • Add wkhtmltopdf for PDF output
      • Create a TOC with doctoc
    • QA feature for optional file exclusions for reviewing
    • Per input file or globally:
      • Find/replace with regex (ex: names, titles, chapter #s, timestamps, etc)
      • Create TOC with doctoc
      • Remove yaml from top of md file



To install the command line tool globally, run:

npm install -g @knennigtri/merge-markdown

Command Line Tool

Use default ./manifest.[md|yaml|yml|json] for input

> merge-markdown

Merge based on manifest file

> merge-markdown -m myManifest.md

Merge based on path/to/files default manifest or merges all files in a default order

> merge-markdown -m path/to/files

Output to PDF

> merge-markdown -m myManifest.md --pdf


Usage: merge-markdown [ARGS]
  -m <manifestFile>                        Path to input folder, yaml, or json manifest
  -v, --version                            Displays version of this package
      --qa                                 QA mode.
      --nolinkcheck                        Skips linkchecking
      --pdf                                Output to PDF. wkhtmltopdf must be installed http://wkhtmltopdf.org/downloads.html
      --html                               Output to HTML
  -h, --help                               Displays this screen
  -h [manifest|options|outputOptions|qa]   See examples
Default manifest: manifest.[md|yaml|yml|json] unless specified in -m. 

Manifest file format

manifest.[md|yaml|yml|json]: This file can be in YAML or JSON format.

  • input: No input will merge all .md files in the same directory as the manifest.
    • myFile1.md: {options} Local options
    • myFile2.md: {options}
  • output: No output will be save the merged doc in in merged/<curDir>.out.md.
  • {options}: global options. See Supported Options

Relative or absolute paths can be used for all values

Supported Options

Options can be applied to an individual input or at a globally to apply to all inputs


Optionlly removes YAML from top of input file. Default=false

  noYAML: true|false


Optionally find/replace in an input file.

  • string: Specify a string to find and replace
  • regex: Specify a regex to find and replace
      <!--{timestamp}-->: 09/01/2022
      ({#(.*?)}): ""                  


Optionally add a table of contents to files using doctoc. This will allow for a local navigation within a module/chapter of your merged document.

# Use Default doctoc values:
 doctoc: true
# Add a unique title:
 doctoc: "Module Contents"
# Fully configure doctoc by overriding the default values from below:
   mode: github
   maxlevel: 3
   title: ""
   notitle: true
   entryprefix: ""
   all: false
   stdout: true
   update-only: false                

Based on doctoc, Set where you would like for the TOC to exist in the markdown file

  <!-- START auto-update -->
  <!-- START doctoc -->
  <!-- END doctoc -->
  <!-- END auto-update -->

Supported Output Options

You can output to HTML or PDF. Pandoc is used to generate HTML and wkhtmltopdf is used to generate a PDF.

Merged file TOC

Similar to adding a TOC to the input files, you can add a TOC for the entire merged document. See doctoc options to configure.

     key: value

HTML Output

You can optionally add pandoc parameters to the manifest. The key doesn't matter, only the value is evalutated based on pandoc args.

     latexTemplate: --template path/to/my/latex/template.latex
     css: -c path/to/my/css/main.css

The following arguments cannot be changes for pandoc:

  • -o < fileName > - can only be modified using manifest.output.name

PDF Output

You can optionally add wkhtmltopdf options to the manifest. wkhtmltopdf must be installed and added to your path to create PDFs!

See wkhtmltopdf options to learn more:

    marginBottom: 1in
    marginTop: 1in
    pageSize: Letter

The following options cannot be changes for wkhtmltopdf:

  • enableLocalFileAccess - always true
  • disableSmartShrinking - always true
  • output - can only be modified using manifest.output.name

Generate HTML only:

 merge-markdown -m manifest.md --html

Generate a PDF:

 merge-markdown -m manifest.md --pdf

Example files can be found in test/pdf/src. You can also checkout a working project for css development using webpack.

Special Modes

QA Mode

> merge-markdown -m manifest.json --qa

Output will omit all filenames with frontmatter by default Add a regex to the manifest.json to customize exclusion:

  qa: {exclude: "(frontmatter|preamble)"}

nolinkcheck Mode

Sometimes the markdown-link-check tool might produce an error. To skip linkcheck:

> merge-markdown -m mymanifest.yml --nolinkcheck

Debug Mode

Debug is used in this tool. Available debug options:

  • index:[ input | manifest ]
  • index:manifest:[ json | generate ]
  • merge:[ relinks | yaml | doctoc | replace | linkcheck ]
  • presentation:[ html | pdf ]:options
  • presentation:verbose

Manifest Examples

YAML used as input

  frontmatter.md: ""
  file1.md: {noYAML: true, doctoc: "#### Section Contents"}
  file2.md: {noYAML: true, doctoc: "#### Section Contents"}
  name: myOutput.md

JSON used as input

  "input": {
    "frontmatter.md": {"replace": {"timestamp":true}},
    "file1.md": {"noYAML":true,"doctoc":"#### Section Contents"},
    "file2.md": {"noYAML":true,"doctoc":"#### Section Contents"}
  "output": {
    "name": "myOutput.md"

Replace keys within a single file

  "input": {
    "folder1/folder1/file1.md": {"replace": {
      "<!--{timestamp}-->": "06/01/2021",
      "<!--{endOfSection}-->": "> To learn more on this subject, visit: www.example.com",
      "({#(.*?)})": ""
    "folder2/folder2/file2.md": {"noYAML":true}
  "output": {
    "name": "path/to/myOutput.md"

Options applied to all files

  frontmatter.md: ""
  folder1/file1.md: ""
  file2.md: ""
  name: myOutput.md
  ${timestamp}: 06/01/2021
  ({#(.*?)}): ""
doctoc: "#### Chapter contents"
noYAML: true

Apply output options

 frontmatter.md: ''
 m1/m1-example.md: {noYAML: true, doctoc: true, replace: {<!--#-->: "Module 1:"}}
 m2/m2-example.md: {noYAML: true, doctoc: true, replace: {<!--#-->: "Module 2:"}}
  name: merged/myOutput.md
   mode: bitbucket
   title: "Course Contents"
   maxlevel: 2
    css: -c path/to/main.css
    title: -M title:Example
    pageSize: Letter
    footerLine: true
    footerCenter: Page [page]


A Dockerfile based on a NodeJS image with all required dependencies is also available on the project.

How to use this image

All you need to do is copy the Dockerfile and docker-compose.yml files inside your project, and set up Docker Compose with the following command:

docker compose up -d --build

Basic execution commands

The docker image will copy all local structure of files and directories of the project into the current image's working directory. Once there, the command merge-markdown needs to be executed on the node service of docker compose to generate the desired output, e.g:

docker compose exec node merge-markdown -m manifest.yml --pdf

We are assuming that the project will contain a manifest.yml file in the root directory. An example of the project file structure could be:

└── assets
    ├── image1.svg
    └── ...
├── docker-compose.yml
├── Dockerfile
├── manifest.yml
├── README.md
├── README_2.md
├── README_3.md
└── README_4.md

Getting the outputs from the container's image could be done with the following command:

docker compose cp node:/home/runner/workspace/output.pdf .

This is an example to get the outcome of an merge-markdown execution which converts markdown files into a PDF.


npm i @knennigtri/merge-markdown

DownloadsWeekly Downloads






Unpacked Size

161 kB

Total Files


Last publish


  • nennig