Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ mdite Public

Markdown documentation toolkit: Treats your docs as a connected graph. Validates links, detects orphans, maps dependencies. Refactor with confidence.

License

Notifications You must be signed in to change notification settings

radleta/mdite

Repository files navigation

mdite

CI Node.js Version License: MIT

Markdown documentation toolkit - Work with your documentation as a connected system, not scattered files.

mdite treats your markdown documentation as a cohesive whole. Map dependencies, validate structure, search across files, and pipe content—all while understanding how your docs connect together.


The Vision

Most tools treat markdown files as isolated documents. mdite treats them as a connected system.

Current Reality

  • 📄 Edit files one at a time
  • 🔍 grep individual files, hope you find everything
  • 🤷 No idea what's connected to what
  • 💥 Break things when refactoring
  • 🗑️ Afraid to delete anything

With mdite

  • 🕸️ See the whole system - Your docs are a graph, visualize it
  • 🔍 Search the system - Query across all connected docs
  • 📊 Understand dependencies - Know what links to what
  • Validate structure - Catch broken links and orphans
  • 🎯 Work confidently - Refactor and clean up without fear

What mdite Does

mdite is a toolkit for working with markdown documentation as a unified system:

📊 Map & Analyze (deps)

# See what connects to what
mdite deps docs/api.md --incoming

# Understand your doc structure
mdite deps README.md --format tree

✅ Validate & Lint (lint)

# Catch broken links and orphans
mdite lint

# CI/CD integration
mdite lint --format json

📋 List Files (files)

# List all reachable files
mdite files

# Filter by depth
mdite files --depth 2

# Search with ripgrep (Unix composition)
mdite files | xargs rg "authentication"

# Filter by frontmatter and process
mdite files --frontmatter "status=='published'" | xargs prettier --write

📤 Export & Pipe (cat)

# Output entire doc system
mdite cat | less

# Pipe to shell tools
mdite cat docs/api/*.md | grep "function"

# Combine with other tools
mdite cat --order deps | pandoc -o book.pdf

The key: mdite understands how your docs connect, so it can treat them as a unified system.


Quick Start

Installation

Note: mdite will be published to npm with the first release. Once published, install via:

npm install -g mdite

For now, you can clone and build from source: git clone https://github.com/radleta/mdite.git && cd mdite && npm install && npm run build && npm link

Three Core Workflows

1. Understand Your Docs (Graph Analysis)

# Map the structure
mdite deps README.md

# What references this file?
mdite deps docs/api.md --incoming

# What does this file reference?
mdite deps docs/guide.md --outgoing

Use case: Before changing anything, understand the impact.

2. Validate Your Docs (Linting)

# Check for issues
mdite lint

# Find orphaned files
mdite lint --verbose

# CI/CD integration
mdite lint --format json

Use case: Catch broken links and structural issues.

3. Configure (Optional)

# Create custom config
mdite init

# See merged config
mdite config

Use case: Customize for your project's needs.


Core Features

🕸️ Documentation as a Graph

mdite builds a complete dependency graph of your documentation starting from an entrypoint (usually README.md), following all internal links.

Why this matters: You can see exactly how your docs connect. No more guessing about structure or dependencies.

mdite deps README.md
# Output:
# README.md
# ├── docs/getting-started.md
# │   ├── docs/installation.md
# │   └── docs/configuration.md
# ├── docs/api-reference.md
# └── docs/guides/

This graph is the foundation for everything mdite does - validation, analysis, search, export.

📊 Dependency Analysis

Understand what connects to what before making changes:

# Impact analysis: What will break if I change this?
mdite deps docs/api.md --incoming
# Shows: README.md, guide.md, tutorial.md all reference it

# Scope analysis: What does this file depend on?
mdite deps docs/guide.md --outgoing
# Shows: Links to setup.md, api.md, troubleshooting.md

Real-world use cases:

  • 🔧 Refactoring: Know the impact before renaming/moving files
  • 🧹 Cleanup: Find files that nothing depends on (safe to delete)
  • 📖 Documentation: Understand your doc structure
  • 🎯 Navigation: Find central hub documents

✅ Structure Validation

Catch issues before they reach users:

Orphan Detection: Find markdown files that aren't linked from anywhere—dead weight in your repo.

mdite lint
# ✗ Found 3 orphaned files:
#   - old-guide.md
#   - deprecated-api.md
#   - scratch-notes.md

Link Validation: Validates three types of links:

  • File links: [guide](./setup.md) → validates file exists
  • Anchor links: [intro](#getting-started) → validates heading exists
  • Cross-file anchors: [api](./api.md#methods) → validates both

Benefit: Zero 404s in your documentation.

🔍 System-Wide Operations

Because mdite understands your docs as a system, it can do things other tools can't:

Export the system:

# Output entire doc system in dependency order
mdite cat --order deps

# Output in alphabetical order
mdite cat --order alpha

# Pipe to shell tools
mdite cat | grep -n "TODO"
mdite cat | wc -l  # Total lines in doc system

# Export as single file
mdite cat --order deps | pandoc -o documentation.pdf

# JSON format with metadata
mdite cat --format json | jq '.[] | {file, wordCount}'

Coming Soon:

⚠️ Note: The following features are planned but not yet implemented. They are shown here to illustrate the project's vision.

Search across the system:

# FUTURE FEATURE - not yet available
# Find all docs mentioning "authentication"
mdite query "authentication" --content

# Find docs matching name pattern
mdite query "api-*" --names

# Search in a specific section of the graph
mdite query "config" --from docs/reference/

Transform the system:

# FUTURE FEATURE - not yet available
# Generate table of contents from graph
mdite toc --depth 2

# Validate external links (HTTP/HTTPS)
mdite lint --external

Why mdite?

The Problem: Documentation is a System, But Tools Treat It Like Files

You have 50 markdown files that form a cohesive documentation site, but:

  • ❌ You edit them one at a time (disconnected)
  • ❌ You search them one at a time (grep file1.md, grep file2.md...)
  • ❌ You have no idea how they connect
  • ❌ Refactoring is terrifying (what will break?)
  • ❌ You don't know what's safe to delete

mdite solves this by treating your docs as a connected graph.

What Makes mdite Different?

Capability Traditional Tools mdite
Link validation ❌ Can't detect broken links ✅ Validates all internal links
Orphan detection ❌ No concept of reachability ✅ Finds unreachable files
Dependency analysis ❌ No understanding of structure ✅ Maps entire graph
System-wide search ❌ Search files individually ✅ Query the whole system
Structural operations ❌ File-by-file only ✅ Operates on connected docs

vs. Traditional Markdown Linters

markdownlint / remark-lint:

  • ✅ Check style (formatting, syntax)
  • ❌ Don't understand document relationships
  • ❌ Can't detect orphaned files
  • ❌ Miss structural issues
  • ❌ File-centric, not system-centric

mdite:

  • ✅ Validates structure and relationships
  • ✅ Detects orphaned files
  • ✅ Maps dependencies
  • ✅ System-centric operations
  • ✅ Understands your docs as a connected whole

Use both: Traditional linters for style, mdite for structure and system operations.


Real-World Workflows

1. Safe Refactoring

# Step 1: Understand the impact
mdite deps docs/old-api.md --incoming
# Shows: README.md, tutorial.md, guide.md reference it

# Step 2: Rename the file
mv docs/old-api.md docs/api-reference.md

# Step 3: Update the 3 files that link to it

# Step 4: Validate
mdite lint
# ✅ All links valid

Benefit: Refactor with confidence, not fear.

2. Documentation Spring Cleaning

# Find orphaned files
mdite lint
# ✗ Found 5 orphaned files

# Review each one
mdite deps old-guide.md --incoming
# Shows: nothing links to it

# Safe to delete!
rm old-guide.md deprecated-api.md scratch-notes.md

# Verify
mdite lint
# ✅ All clean, only connected docs remain

Benefit: Clean repos, confident deletions.

3. Pre-Release Documentation Check

# Validate structure
mdite lint

# Check for orphans (incomplete docs)
mdite lint --verbose | grep "orphan"

# Verify all API docs are reachable
mdite deps README.md --format list | grep "api"

# Green light to release
mdite lint --format json
# Exit code 0 = ship it

Benefit: Never ship broken documentation.

4. Understanding a New Codebase

# Start at the entry point
mdite deps README.md --depth 1
# Shows: Top-level structure

# Explore a section
mdite deps docs/architecture.md
# Shows: What it connects to

# Find all API docs
mdite deps README.md --format list | grep api
# Lists all API documentation files

Benefit: Quickly understand documentation structure.

5. CI/CD Quality Gate

# .github/workflows/docs.yml
name: Documentation Quality

on: [pull_request]

jobs:
  validate-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install -g mdite
      - run: mdite lint --format json
      # Fails if broken links or orphans detected

Benefit: Documentation quality is enforced, not hoped for.

6. Unix Tool Integration (Piping & Scripting)

# Find all files with broken links
mdite lint | grep "Dead link" | cut -d: -f1 | sort | uniq

# Count errors by type
mdite lint | grep -o "\\[.*\\]" | sort | uniq -c

# Get JSON summary with jq
mdite lint --format json | jq '[.[] | .severity] | group_by(.) | map({severity: .[0], count: length})'

# List all orphaned files
mdite lint --format json | jq -r '.[] | select(.rule=="orphan-files") | .file'

# Check if specific file has errors
mdite lint | grep "docs/api.md" && echo "API docs need fixing"

# Quiet mode for scripting (no progress messages)
ERRORS=$(mdite lint --quiet 2>/dev/null)
if [ -n "$ERRORS" ]; then
  echo "$ERRORS" | mail -s "Doc errors" [email protected]
fi

# Analyze dependencies
mdite deps README.md --format json | jq '.stats.totalFiles'

# Find deeply nested docs
mdite deps README.md --format json | jq '.outgoing[] | select(.depth > 3) | .file'

# Export dependency graph as CSV
mdite deps README.md --format json | jq -r '.outgoing[] | [.file, .depth] | @csv'

Benefit: Full integration with Unix ecosystem (grep, jq, awk, sed, mail, etc.)

7. Automated Link Fixing with Grep Format

# Find all dead links with literal paths (grep format)
mdite lint --format grep > dead-links.tsv

# Extract just the literal link text (field 7)
mdite lint --format grep | cut -d$'\t' -f7

# Extract file, line, and literal for manual fixing
mdite lint --format grep | awk -F'\t' '{print $1 ":" $2 " → " $7}'

# Automated fix workflow example
mdite lint --format grep | while IFS=$'\t' read file line col endCol severity rule literal resolved; do
  if [ "$rule" = "dead-link" ]; then
    echo "Fix: $file:$line - Replace '$literal' with correct path"
    # Add your automated fix logic here (sed, etc.)
  fi
done

# Extract broken links by file
mdite lint --format grep | awk -F'\t' '$6=="dead-link" {print $1, $7}' | sort

# Count broken links by type
mdite lint --format grep | cut -d$'\t' -f6 | sort | uniq -c

Benefit: Automated fix scripts can locate and replace broken links using exact text from source files, no path reverse-engineering needed.

8. Progressive Validation

# Start with core docs only
mdite lint --depth 1

# Gradually expand validation
mdite lint --depth 2
mdite lint --depth 3

# Finally, full validation
mdite lint

Benefit: Incremental adoption of mdite in large doc repos, validate core docs first.


Commands

Global Options

These options work with all commands:

  • --config <path> - Path to custom config file
  • --colors - Force colored output (even when piped)
  • --no-colors - Disable colored output
  • -q, --quiet - Quiet mode (suppress informational output, show only data/errors)
  • --verbose - Enable verbose/debug output
  • -V, --version - Output the version number
  • -h, --help - Display help for command

Usage:

# Use verbose mode with any command
mdite lint --verbose
mdite deps README.md --verbose

# Quiet mode for scripting (only data/errors, no info messages)
mdite lint --quiet
mdite deps README.md --quiet --format json | jq '.stats'

# Use custom config with any command
mdite lint --config custom-config.js
mdite init --config .mditerc.json

# Control colors
mdite lint --no-colors              # Disable colors
mdite lint --colors | less -R       # Force colors even when piped

Color Detection:

mdite automatically detects whether colors should be used:

  • Auto-enabled when output is a terminal (TTY)
  • Auto-disabled when piped to other tools
  • Force with --colors to override detection
  • Disable with --no-colors or NO_COLOR=1 env var

Environment Variables:

  • NO_COLOR - Disable colors (respects no-color.org standard)
  • FORCE_COLOR - Force colors even when not a TTY
  • CI=true - Disables colors in CI environments (unless FORCE_COLOR is set)

mdite deps <file> - Analyze Dependencies

Visualize and analyze documentation structure.

# Tree view of dependencies
mdite deps README.md

# What references this file? (incoming)
mdite deps docs/api.md --incoming

# What does this file reference? (outgoing)
mdite deps docs/guide.md --outgoing

# Limit depth
mdite deps README.md --depth 2

# JSON output for tooling
mdite deps docs/api.md --format json

# List format
mdite deps README.md --format list

Options:

  • --incoming - Show what references this file
  • --outgoing - Show what this file references
  • --depth <n> - Limit traversal depth
  • --format <type> - Output: tree (default), list, or json

Use cases:

  • 🔍 Impact analysis before refactoring
  • 🧹 Finding safe-to-delete files
  • 📊 Understanding documentation structure
  • 🎯 Identifying central hub documents

mdite lint [path] - Validate Structure

Check documentation for structural issues.

# Lint from current directory
mdite lint

# Lint specific directory
mdite lint ./docs

# JSON output for CI/CD (auto-disables colors)
mdite lint --format json

# Grep format for automated fixes (tab-delimited)
mdite lint --format grep

# Extract all literal paths
mdite lint --format grep | cut -d$'\t' -f7

# Extract file and literal for processing
mdite lint --format grep | awk -F'\t' '{print $1, $7}'

# Pipe JSON to jq for analysis
mdite lint --format json | jq '.[] | select(.severity=="error")'

# Quiet mode for scripting (only errors shown)
mdite lint --quiet

# Verbose output (shows debug info to stderr)
mdite lint --verbose

# NEW: Lint multiple files as entry points
mdite lint README.md docs/api.md docs/guide.md --depth 1

# Perfect for pre-commit hooks (lint only changed files)
CHANGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.md$')
mdite lint $CHANGED --depth 1

Multi-File Validation (NEW)

Lint multiple specific files as independent entry points:

# Lint multiple entry points
mdite lint core/api.md core/cli.md core/config.md

# Each file starts at depth 0
# Results are merged and deduplicated
# Orphans = files not reachable from ANY entry point

Use Cases:

  • Pre-commit hooks: Lint only changed markdown files
  • Selective validation: Check specific docs without full traversal
  • CI/CD: Parallel validation of independent sections
  • Author workflow: Work on multiple related docs

Example:

# Pre-commit: validate changed files and their immediate links
mdite lint $(git diff --cached --name-only | grep '\.md$') --depth 1

Options:

  • --format <type> - Output: text (default), json, or grep
  • --entrypoint <file> - Entrypoint file (overrides config, cannot be used with multiple files)
  • --depth <n> - Maximum depth of traversal (default: unlimited, applies to all files)
  • -q, --quiet - Suppress informational output (only show errors)

Global options (apply to all commands):

  • --config <path> - Custom config file
  • --no-colors - Disable colored output
  • --verbose - Detailed output

Output Streams:

  • stdout - Validation results (errors, warnings)
  • stderr - Informational messages (progress, summaries)

This separation makes mdite pipe-friendly:

# Grep for specific errors
mdite lint | grep "Dead link"

# Count errors
mdite lint | wc -l

# Process JSON with jq
mdite lint --format json | jq '.[] | .file' | sort | uniq

# Suppress progress messages, keep only errors
mdite lint 2>/dev/null

What it validates:

  • ✅ All files reachable from entrypoint
  • ✅ No orphaned files
  • ✅ All file links are valid
  • ✅ All anchor references exist
  • ✅ No broken cross-file anchor links

mdite cat [files...] - Output Documentation Content

Output documentation content in various formats and orderings.

# Output all files in dependency order (default)
mdite cat

# Output in alphabetical order
mdite cat --order alpha

# Use custom separator between files
mdite cat --separator "\\n---\\n"

# Output as JSON with metadata
mdite cat --format json

# Pipe to other tools
mdite cat | grep "TODO"
mdite cat | wc -l

# Export as single file
mdite cat --order deps | pandoc -o docs.pdf

# Combine with jq for analysis
mdite cat --format json | jq '.[] | {file, wordCount}'

Options:

  • [files...] - Specific files to output (optional, defaults to all files in graph)
  • --order <type> - Output order: deps (dependency order, default) or alpha (alphabetical)
  • --separator <text> - Text between files (default: \n\n). Supports escape sequences like \n, \t
  • --format <type> - Output format: markdown (default) or json
  • --exclude <pattern...> - Exclude file patterns (gitignore-style)
  • --respect-gitignore - Respect .gitignore patterns
  • --no-exclude-hidden - Don't exclude hidden directories

Output Formats:

Markdown (default):

  • Outputs raw file content concatenated with separators
  • Perfect for piping to other tools
  • Streams to stdout for efficiency

JSON:

  • Structured output with metadata for each file
  • Includes: file path, depth, content, word count, line count
  • Ideal for programmatic processing

Use cases:

  • 📤 Export: Create single-file documentation artifacts
  • 🔄 Transform: Pipe to pandoc, markdown processors, or custom tools
  • 📊 Analyze: Extract statistics, search patterns, or validate content
  • 🎯 Integration: Build documentation pipelines and workflows

Examples:

# Generate PDF documentation
mdite cat --order deps | pandoc --toc -o documentation.pdf

# Count total words in documentation
mdite cat | wc -w

# Find all TODOs across documentation
mdite cat | grep -n "TODO"

# Get statistics from JSON
mdite cat --format json | jq '[.[] | .wordCount] | add'

# Extract code blocks
mdite cat | awk '/```/,/```/'

mdite files - List Files in Documentation Graph

Unix Philosophy Approach: mdite provides graph-filtered file lists that compose with the Unix ecosystem.

# List all reachable files
mdite files

# Filter by depth
mdite files --depth 2

# List orphaned files only
mdite files --orphans

# Output absolute paths
mdite files --absolute

# Filter by frontmatter metadata (JMESPath query)
mdite files --frontmatter "status=='published'"
mdite files --frontmatter "contains(tags, 'api')"

# JSON output with metadata
mdite files --format json

# Annotate with depth information
mdite files --with-depth

# Null-separated for xargs -0
mdite files --print0 | xargs -0 ls -l

# Sort by depth, incoming, outgoing links, or alphabetically
mdite files --sort depth
mdite files --sort incoming
mdite files --sort outgoing
mdite files --sort alpha  # default

Unix Composition (The Power of Files):

The files command is designed to compose with standard Unix tools via pipes:

# Search with ripgrep (graph-filtered search)
mdite files --depth 2 | xargs rg "authentication" -C 2

# Update published docs only
mdite files --frontmatter "status=='published'" | xargs sed -i 's/v1/v2/g'

# Lint reachable docs
mdite files | xargs markdownlint
mdite files | xargs prettier --write

# Generate stats
mdite files | xargs wc -w | tail -1  # Total words

# Archive orphaned files
mdite files --orphans | xargs -I {} mv {} archive/

# Complex pipeline: find API docs, extract code blocks, count languages
mdite files --frontmatter "contains(tags, 'api')" | \
  xargs rg '```(\w+)' -o -r '$1' | \
  sort | uniq -c | sort -rn

# Custom processing
mdite files | xargs ./my-script.sh

Options:

  • --depth <n> - Limit to files at depth N or less (default: unlimited)
  • --orphans - List only orphaned files
  • --no-orphans - Exclude orphaned files (default)
  • --absolute - Output absolute paths (default: relative)
  • --frontmatter <query> - Filter by frontmatter metadata (JMESPath query)
  • --format <type> - Output format: list (default) or json
  • --with-depth - Annotate output with depth information (list format only)
  • --print0 - Use null character as separator (for xargs -0)
  • --sort <type> - Sort by: alpha (default), depth, incoming, outgoing
  • --exclude <pattern...> - Exclude file patterns (gitignore-style)
  • --respect-gitignore - Respect .gitignore patterns
  • --no-exclude-hidden - Don't exclude hidden directories

Why files instead of query?

Following Unix philosophy, mdite focuses on what it does best: graph operations. Instead of reimplementing search (ripgrep is better), mdite provides graph-filtered file lists that compose with ANY tool:

  • Use ripgrep for search - It's faster and more feature-rich
  • Use sed/awk for transformation - They're mature and powerful
  • Use custom scripts - Unlimited flexibility
  • Infinite combinations - Not locked into mdite's features

Use cases:

  • 🔍 Graph-aware search - Filter files by graph/metadata, search with ripgrep
  • 🔄 Bulk operations - Process graph-filtered files with any tool
  • 📊 Metadata filtering - JMESPath queries on frontmatter combined with graph
  • 🧹 Cleanup - Find and archive orphaned files
  • 🎯 Targeted operations - Work on specific subsets of your documentation

mdite init - Initialize Configuration

Create a configuration file.

# Create default config file (mdite.config.js)
mdite init

# Create config file with custom path
mdite init --config .mditerc.json

Options:

  • --config <path> - Config file path (default: mdite.config.js)

mdite config - Explore Configuration

Display or explore mdite configuration.

# View current merged configuration
mdite config

# View all available options
mdite config --schema

# Learn about specific option
mdite config --explain maxConcurrency

# Generate comprehensive template
mdite config --template > mdite.config.js

# See where each value comes from (Phase 2 - not yet implemented)
mdite config --sources

Options:

  • --schema - Display all configuration options with descriptions, types, defaults
  • --explain <key> - Show detailed explanation of a specific option
  • --template - Generate comprehensive config template
  • --sources - Show which layer provides each value (planned for Phase 2)
  • --format <type> - Output format: text (default), json, js, yaml, md

Use cases:

  • 🔍 Discover options: See what's configurable without leaving terminal
  • 📖 Learn about options: Get detailed help for specific configuration keys
  • 🎯 Generate templates: Create well-documented config files quickly
  • 🐛 Debug config: Understand where values come from (planned)

Future Commands

⚠️ Note: These commands are planned for future releases and are not yet available.

Coming soon as mdite expands:

mdite toc - Generate Table of Contents

# FUTURE FEATURE - not yet available
# Generate TOC from graph
mdite toc --depth 2

mdite stats - Documentation Metrics

# FUTURE FEATURE - not yet available
# Analyze documentation metrics
mdite stats --depth 2

Configuration

Zero Config

mdite works out of the box:

mdite lint  # Just works
mdite deps README.md  # Just works

Defaults:

  • Entrypoint: README.md
  • All rules: error
  • Output: colored text

Discovering Options

mdite provides built-in help for configuration:

# See all available options
mdite config --schema

# Learn about specific option
mdite config --explain maxConcurrency

# Generate comprehensive template
mdite config --template > mdite.config.js

All configuration options are self-documented - no need to search docs!

Custom Configuration

Create mdite.config.js for project-specific settings:

module.exports = {
  // Start traversal from a different file
  entrypoint: 'docs/index.md',

  // Customize rule severity
  rules: {
    'orphan-files': 'error', // Block build on orphans
    'dead-link': 'error', // Block build on broken links
    'dead-anchor': 'warn', // Warn but don't block
  },
};

Configuration Formats

Format File Use Case
JavaScript mdite.config.js Comments, computed values
JSON .mditerc Simple, no comments
YAML .mditerc.yaml Human-readable, comments
package.json "mdite": {} Keep config in one place

Priority: CLI flags > Project config > Defaults

See examples/06-config-variations for working examples.

Rules

Rule What It Detects Default
orphan-files Files unreachable from entrypoint error
dead-link Broken relative file links error
dead-anchor Broken #heading references error

Severity levels:

  • error - Fail (exit code 1)
  • warn - Show warning, don't fail
  • off - Disable rule

Exit Codes

mdite follows Unix conventions for exit codes:

Code Meaning When
0 Success No validation errors found
1 Validation Error Orphaned files, broken links, or validation failures
2 Usage Error Invalid arguments, unknown options, or configuration errors
130 Interrupted Process interrupted (Ctrl+C, SIGINT, SIGTERM)

Usage in scripts:

# Check exit code
if mdite lint; then
  echo "Documentation is valid"
else
  echo "Documentation has errors"
  exit 1
fi

# CI/CD pipeline
mdite lint --format json || exit 1

# Conditional logic
mdite lint && npm run deploy

# Capture exit code
mdite lint
EXIT_CODE=$?
if [ $EXIT_CODE -eq 1 ]; then
  echo "Validation errors found"
elif [ $EXIT_CODE -eq 2 ]; then
  echo "Usage error - check your command"
fi

Signal Handling:

mdite gracefully handles Unix signals:

  • SIGINT (Ctrl+C) - Clean exit with code 130
  • SIGTERM - Clean exit with code 130
  • SIGPIPE - Gracefully exits when pipe is closed (e.g., mdite lint | head)

Example Output

mdite lint - Validation

mdite
──────────────────────────────────────────────────
ℹ Linting: ./docs
ℹ Entrypoint: README.md

ℹ Building dependency graph...
✓ Found 24 reachable files

ℹ Checking for orphaned files...
✗ Found 3 orphaned files

ℹ Validating links...
✗ Found 2 link errors


Found 5 issue(s)
──────────────────────────────────────────────────

docs/old-guide.md
  - error Orphaned file: not reachable from entrypoint [orphan-files]

docs/setup.md
  7:3 error Dead link: installation.md [dead-link]

✗ 5 error(s), 0 warning(s)

mdite deps - Dependency Analysis

$ mdite deps README.md --depth 2

Dependencies for README.md
──────────────────────────────────────────────────

Outgoing (what this file references):
├── docs/getting-started.md
│   ├── docs/installation.md
│   └── docs/configuration.md
├── docs/api-reference.md
│   ├── docs/api/methods.md
│   └── docs/api/types.md
└── CONTRIBUTING.md

Incoming (what references this file):
(none - this is the entrypoint)

Cycles detected: 0

Examples

The examples/ directory contains 12 runnable demonstrations (68 files) showing mdite in action:

# Valid documentation
cd examples/01-valid-docs && mdite lint

# Orphan detection
cd examples/02-orphan-files && mdite lint

# Broken links
cd examples/03-broken-links && mdite lint

# Dependency analysis
cd examples/01-valid-docs && mdite deps README.md

Run all examples:

cd examples && ./run-all-examples.sh

See examples/README.md for complete documentation.


How It Works

The Graph Model

mdite treats your documentation as a directed graph:

  • Nodes: Markdown files
  • Edges: Links between files
  • Root: Entrypoint file (default: README.md)
README.md (root)
├─→ docs/guide.md
│   ├─→ docs/setup.md
│   └─→ docs/api.md
└─→ CONTRIBUTING.md
    └─→ docs/development.md

Graph Building Algorithm

  1. Start at entrypoint (README.md)
  2. Parse markdown to extract links
  3. Follow each relative .md link
  4. Recursively build graph (with cycle detection)
  5. Result: Complete map of connected documentation

What gets included:

  • ✅ Relative links: [guide](./setup.md)
  • ✅ Links with anchors: [api](./api.md#methods)
  • ✅ Anchor-only: [intro](#getting-started)

What gets skipped:

  • ❌ External URLs: https://example.com
  • ❌ Absolute paths outside project
  • ❌ Non-markdown files

Validation Using the Graph

Once the graph is built, mdite can:

  • Detect orphans: Files NOT in the graph
  • Validate links: Check edges point to existing nodes
  • Analyze dependencies: Traverse graph in any direction
  • Future: Query, search, export the graph

This graph foundation enables all current and future mdite features.


Roadmap

mdite is evolving from a linter into a complete documentation toolkit.

✅ Current

  • Graph-based dependency analysis (deps)
  • Structural validation (lint)
  • Orphan detection
  • Link validation (file + anchor)
  • Configuration system
  • Content output (cat) - Export documentation content
    • Dependency-order and alphabetical output
    • JSON format with metadata
    • Pipe-friendly for Unix workflows

🚧 Future Features

⚠️ Note: These features are planned for future releases and are not yet implemented.

  • mdite query - Search across documentation system
    • Content search
    • Filename pattern matching
    • Scope to graph sections
  • mdite toc - Generate table of contents from graph
  • mdite stats - Documentation metrics and analysis
  • External link validation - Check HTTP/HTTPS URLs
  • Watch mode - Auto-validate on file changes
  • LSP server - Editor integration
  • Custom rule API - Write your own validation rules
  • Export formats - PDF, HTML, etc. with graph awareness

The vision: A complete toolkit for working with markdown documentation as a unified, connected system.


Integration

Pre-Commit Hook (Husky)

{
  "husky": {
    "hooks": {
      "pre-commit": "mdite lint"
    }
  }
}

GitHub Actions

name: Documentation

on:
  pull_request:
    paths:
      - 'docs/**'
      - '*.md'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install -g mdite
      - run: mdite lint --format json

Package.json Scripts

{
  "scripts": {
    "docs:lint": "mdite lint",
    "docs:deps": "mdite deps README.md",
    "docs:check": "mdite lint && echo '✓ Documentation valid'",
    "predeploy": "mdite lint"
  }
}

Contributing

mdite is evolving rapidly. Contributions welcome!

See CONTRIBUTING.md for:

  • Development setup
  • Testing guidelines
  • Pull request process
  • Roadmap and feature ideas

License

MIT © 2025 Richard Adleta


About

mdite (markdown documentation toolkit) is built for developers and teams who work with interconnected markdown documentation.

Born from the frustration of broken docs and the realization that documentation is a system, not a collection of files, mdite provides the tools to work with that system effectively.

Built with:

Issues & Ideas: GitHub Issues


Work with your documentation as a system, not scattered files.

npm install -g mdite
mdite deps README.md    # Understand structure
mdite lint              # Validate integrity