markdownlint-integration

Markdownlint Integration

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "markdownlint-integration" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-markdownlint-integration

Markdownlint Integration

Master integrating markdownlint into development workflows including CLI usage, programmatic API (sync/async/promise), CI/CD pipelines, pre-commit hooks, and editor integration.

Overview

Markdownlint can be integrated into various parts of your development workflow to ensure consistent markdown quality. This includes command-line tools, programmatic usage in Node.js, continuous integration pipelines, Git hooks, and editor plugins.

Command-Line Interface

markdownlint-cli Installation

npm install -g markdownlint-cli

or as dev dependency

npm install --save-dev markdownlint-cli

Basic CLI Usage

Lint all markdown files in current directory

markdownlint '**/*.md'

Lint specific files

markdownlint README.md CONTRIBUTING.md

Lint with configuration file

markdownlint -c .markdownlint.json '**/*.md'

Ignore specific files

markdownlint '**/*.md' --ignore node_modules

Fix violations automatically

markdownlint -f '**/*.md'

Output to file

markdownlint '**/*.md' -o linting-results.txt

Advanced CLI Options

Use custom config

markdownlint --config config/markdown-lint.json docs/

Ignore patterns from file

markdownlint --ignore-path .gitignore '**/*.md'

Use multiple ignore patterns

markdownlint --ignore node_modules --ignore dist '**/*.md'

Enable specific rules only

markdownlint --rules MD001,MD003,MD013 '**/*.md'

Disable specific rules

markdownlint --disable MD013 '**/*.md'

Show output in JSON format

markdownlint --json '**/*.md'

Quiet mode (exit code only)

markdownlint -q '**/*.md'

Verbose output

markdownlint --verbose '**/*.md'

CLI Configuration File

.markdownlint-cli.json :

{ "config": { "default": true, "MD013": { "line_length": 100 } }, "files": ["/*.md"], "ignores": [ "node_modules/", "dist/", "build/" ] }

Use with:

markdownlint --config .markdownlint-cli.json

Programmatic API

Callback-Based API

const markdownlint = require('markdownlint');

const options = { files: ['good.md', 'bad.md'], config: { default: true, 'line-length': { line_length: 100 } } };

markdownlint(options, (err, result) => { if (!err) { console.log(result.toString()); } else { console.error(err); } });

Promise-Based API

import { lint as lintPromise } from 'markdownlint/promise';

const options = { files: ['README.md', 'docs/**/*.md'], config: { default: true, 'no-inline-html': { allowed_elements: ['br', 'img'] } } };

try { const results = await lintPromise(options); console.dir(results, { colors: true, depth: null }); } catch (err) { console.error(err); }

Synchronous API

import { lint as lintSync } from 'markdownlint/sync';

const options = { files: ['README.md'], strings: { 'inline-content': '# Test\n\nContent here.' }, config: { default: true } };

const results = lintSync(options); console.log(results.toString());

Linting Strings

const markdownlint = require('markdownlint');

const options = { strings: { 'content-1': '# Heading\n\nParagraph text.', 'content-2': '## Another heading\n\nMore content.' }, config: { default: true, 'first-line-heading': { level: 1 } } };

markdownlint(options, (err, result) => { if (!err) { const resultString = result.toString(); console.log(resultString); } });

Working with Results

import { lint } from 'markdownlint/promise';

const results = await lint({ files: ['docs/**/*.md'], config: { default: true } });

// Results is an object keyed by filename Object.keys(results).forEach(file => { const fileResults = results[file];

fileResults.forEach(result => { console.log(${file}:${result.lineNumber} ${result.ruleNames.join('/')} ${result.ruleDescription});

if (result.errorDetail) {
  console.log(`  Detail: ${result.errorDetail}`);
}

if (result.errorContext) {
  console.log(`  Context: ${result.errorContext}`);
}

}); });

Reading Configuration

const markdownlint = require('markdownlint'); const { readConfigSync } = require('markdownlint/sync');

// Read configuration from file const config = readConfigSync('.markdownlint.json');

const options = { files: ['**/*.md'], config: config };

const results = markdownlint.sync(options); console.log(results.toString());

Using Custom Rules

const markdownlint = require('markdownlint'); const customRule = require('./custom-rules/heading-capitalization');

const options = { files: ['README.md'], config: { default: true, 'heading-capitalization': true }, customRules: [customRule] };

markdownlint(options, (err, result) => { if (!err) { console.log(result.toString()); } });

Applying Fixes Programmatically

applyFix Function

const { applyFix } = require('markdownlint');

const line = ' Text with extra spaces '; const fixInfo = { editColumn: 1, deleteCount: 2, insertText: '' };

const fixed = applyFix(line, fixInfo); console.log(fixed); // 'Text with extra spaces '

applyFixes Function

const { applyFixes } = require('markdownlint');

const input = '# Heading\n\n\nParagraph'; const errors = [ { lineNumber: 3, ruleNames: ['MD012'], ruleDescription: 'Multiple blank lines', fixInfo: { lineNumber: 3, deleteCount: -1 } } ];

const fixed = applyFixes(input, errors); console.log(fixed); // '# Heading\n\nParagraph'

Auto-Fix Workflow

const fs = require('fs'); const markdownlint = require('markdownlint'); const { applyFixes } = require('markdownlint');

const file = 'README.md'; const content = fs.readFileSync(file, 'utf8');

const options = { strings: { [file]: content }, config: { default: true } };

markdownlint(options, (err, result) => { if (!err) { const errors = result[file] || [];

if (errors.length > 0) {
  const fixed = applyFixes(content, errors);
  fs.writeFileSync(file, fixed, 'utf8');
  console.log(`Fixed ${errors.length} issues in ${file}`);
}

} });

CI/CD Integration

GitHub Actions

.github/workflows/markdownlint.yml :

name: Markdownlint user-invocable: false

on: push: branches: [main, develop] pull_request: branches: [main]

jobs: lint: runs-on: ubuntu-latest

steps:
  - name: Checkout code
    uses: actions/checkout@v3

  - name: Setup Node.js
    uses: actions/setup-node@v3
    with:
      node-version: '18'

  - name: Install dependencies
    run: npm ci

  - name: Run markdownlint
    run: npx markdownlint '**/*.md' --ignore node_modules

  - name: Annotate PR with results
    if: failure()
    run: |
      npx markdownlint '**/*.md' --ignore node_modules -o markdownlint-results.txt
      cat markdownlint-results.txt

GitHub Actions with markdownlint-cli2

name: Markdownlint user-invocable: false

on: [push, pull_request]

jobs: lint: runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v3

  - name: Run markdownlint-cli2
    uses: DavidAnson/markdownlint-cli2-action@v9
    with:
      paths: '**/*.md'

GitLab CI

.gitlab-ci.yml :

markdownlint: image: node:18-alpine stage: test before_script: - npm install -g markdownlint-cli script: - markdownlint '**/*.md' --ignore node_modules only: - merge_requests - main artifacts: when: on_failure paths: - markdownlint-results.txt

CircleCI

.circleci/config.yml :

version: 2.1

jobs: markdownlint: docker: - image: cimg/node:18.0 steps: - checkout - run: name: Install markdownlint command: npm install -g markdownlint-cli - run: name: Run linter command: markdownlint '**/*.md' --ignore node_modules

workflows: version: 2 build_and_test: jobs: - markdownlint

Jenkins Pipeline

Jenkinsfile :

pipeline { agent any

stages {
    stage('Lint Markdown') {
        steps {
            sh 'npm install -g markdownlint-cli'
            sh 'markdownlint "**/*.md" --ignore node_modules'
        }
    }
}

post {
    always {
        cleanWs()
    }
    failure {
        echo 'Markdownlint found issues!'
    }
}

}

Azure Pipelines

azure-pipelines.yml :

trigger:

  • main

pool: vmImage: 'ubuntu-latest'

steps:

  • task: NodeTool@0 inputs: versionSpec: '18.x' displayName: 'Install Node.js'

  • script: | npm install -g markdownlint-cli displayName: 'Install markdownlint'

  • script: | markdownlint '**/*.md' --ignore node_modules displayName: 'Run markdownlint'

Pre-commit Hooks

Using Husky

Install Husky:

npm install --save-dev husky npx husky install

Create pre-commit hook:

npx husky add .husky/pre-commit "npm run lint:md"

Add script to package.json :

{ "scripts": { "lint:md": "markdownlint '/*.md' --ignore node_modules", "lint:md:fix": "markdownlint -f '/*.md' --ignore node_modules" } }

Using lint-staged

Install lint-staged:

npm install --save-dev lint-staged

Configure in package.json :

{ "lint-staged": { "*.md": [ "markdownlint --fix", "git add" ] } }

Update pre-commit hook:

npx husky add .husky/pre-commit "npx lint-staged"

Using pre-commit Framework

.pre-commit-config.yaml :

repos:

Install and use:

pip install pre-commit pre-commit install pre-commit run --all-files

Editor Integration

Visual Studio Code

Install the markdownlint extension:

  • Open VS Code

  • Go to Extensions (Cmd+Shift+X)

  • Search for "markdownlint"

  • Install "markdownlint" by David Anson

Configure in .vscode/settings.json :

{ "markdownlint.config": { "default": true, "MD013": { "line_length": 100 } }, "markdownlint.ignore": [ "node_modules/", "dist/" ], "editor.codeActionsOnSave": { "source.fixAll.markdownlint": true } }

Vim/Neovim

Using ALE (Asynchronous Lint Engine):

" In .vimrc or init.vim let g:ale_linters = { \ 'markdown': ['markdownlint'], }

let g:ale_fixers = { \ 'markdown': ['markdownlint'], }

let g:ale_markdown_markdownlint_options = '-c .markdownlint.json'

" Enable fixing on save let g:ale_fix_on_save = 1

Sublime Text

Install via Package Control:

  • Install Package Control

  • Install "SublimeLinter"

  • Install "SublimeLinter-contrib-markdownlint"

Configure in preferences:

{ "linters": { "markdownlint": { "args": ["-c", ".markdownlint.json"] } } }

Atom

Install packages:

apm install linter-markdownlint

Configure in Atom settings or .atom/config.cson :

"linter-markdownlint": configPath: ".markdownlint.json"

npm Scripts Integration

package.json Scripts

{ "scripts": { "lint": "npm run lint:md", "lint:md": "markdownlint '/*.md' --ignore node_modules", "lint:md:fix": "markdownlint -f '/.md' --ignore node_modules", "lint:md:ci": "markdownlint '**/.md' --ignore node_modules -o markdownlint-report.txt", "test": "npm run lint && npm run test:unit", "precommit": "lint-staged" } }

Cross-Platform Compatibility

Using cross-env for environment variables:

{ "scripts": { "lint:md": "cross-env NODE_ENV=development markdownlint '**/*.md'" }, "devDependencies": { "cross-env": "^7.0.3" } }

Docker Integration

Dockerfile

FROM node:18-alpine

WORKDIR /app

Install markdownlint globally

RUN npm install -g markdownlint-cli

Copy markdown files

COPY . .

Run linter

CMD ["markdownlint", "**/*.md", "--ignore", "node_modules"]

docker-compose.yml

version: '3.8'

services: markdownlint: image: node:18-alpine working_dir: /app volumes: - .:/app command: > sh -c "npm install -g markdownlint-cli && markdownlint '**/*.md' --ignore node_modules"

Run with:

docker-compose run markdownlint

Monorepo Integration

Workspace Configuration

Root .markdownlint.json :

{ "default": true, "line-length": { "line_length": 100 } }

Root package.json :

{ "scripts": { "lint:md": "markdownlint '**/*.md' --ignore node_modules", "lint:md:packages": "lerna run lint:md", "lint:md:all": "npm run lint:md && npm run lint:md:packages" } }

Package-level packages/api/package.json :

{ "scripts": { "lint:md": "markdownlint '**/*.md'" } }

Using Lerna

{ "scripts": { "lint:md": "lerna run lint:md --stream" } }

Using Turborepo

turbo.json :

{ "pipeline": { "lint:md": { "outputs": [] } } }

Reporting and Metrics

Generate HTML Report

Using a custom script:

const fs = require('fs'); const markdownlint = require('markdownlint');

const options = { files: ['**/*.md'], config: { default: true } };

markdownlint(options, (err, results) => { if (!err) { const html = generateHtmlReport(results); fs.writeFileSync('markdownlint-report.html', html); } });

function generateHtmlReport(results) { let html = '<html><head><title>Markdownlint Report</title></head><body>'; html += '<h1>Markdownlint Results</h1>';

Object.keys(results).forEach(file => { html += &#x3C;h2>${file}&#x3C;/h2>; html += '<ul>';

results[file].forEach(result => {
  html += `&#x3C;li>Line ${result.lineNumber}: ${result.ruleDescription}&#x3C;/li>`;
});

html += '&#x3C;/ul>';

});

html += '</body></html>'; return html; }

JSON Output for Tooling

markdownlint '**/*.md' --json > results.json

Process with jq:

markdownlint '**/*.md' --json | jq '.[] | select(length > 0)'

When to Use This Skill

  • Setting up markdownlint in new projects

  • Integrating linting into CI/CD pipelines

  • Configuring pre-commit hooks

  • Automating documentation quality checks

  • Setting up editor integration

  • Building custom linting workflows

  • Creating automated fix scripts

  • Implementing documentation standards

Best Practices

  • CI/CD Integration - Always run linting in continuous integration

  • Pre-commit Hooks - Catch issues before they reach version control

  • Editor Integration - Get real-time feedback while writing

  • Consistent Configuration - Use same config across all environments

  • Auto-fix When Possible - Use -f flag to automatically fix violations

  • Fail Fast - Configure CI to fail on linting errors

  • Ignore Generated Files - Exclude build artifacts and dependencies

  • Version Lock - Pin markdownlint version in package.json

  • Document Standards - Keep documentation on linting rules

  • Progressive Enhancement - Start with relaxed rules, tighten over time

  • Team Communication - Discuss rule changes before applying

  • Regular Updates - Keep markdownlint updated for bug fixes

  • Performance Optimization - Use appropriate glob patterns

  • Error Reporting - Configure meaningful error output

  • Backup Before Auto-fix - Always commit before running fixes

Common Pitfalls

  • Missing Ignore Patterns - Linting node_modules or build directories

  • Wrong Glob Patterns - Incorrect file matching in CLI

  • Config Not Found - Configuration file in wrong location

  • Async/Sync Mismatch - Using sync API with async rules

  • CI Timeout - Linting too many files without optimization

  • No Exit Code Check - Not failing CI on linting errors

  • Overwriting Files - Using auto-fix without version control

  • Missing Dependencies - Not installing markdownlint in CI

  • Platform Differences - Path separators differ between OS

  • Large Binary Files - Accidentally linting non-markdown files

  • Outdated Cache - Cached node_modules with old markdownlint

  • Silent Failures - Not capturing error output in CI

  • Config Conflicts - Multiple config files conflicting

  • Missing Editor Config - Local linting differs from CI

  • No Pre-commit Hook - Issues not caught before commit

Resources

  • markdownlint GitHub Repository

  • markdownlint-cli

  • markdownlint-cli2

  • markdownlint VS Code Extension

  • GitHub Actions Integration

  • API Documentation

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

atomic-design-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review