@redocly/recheck
v0.1.0
Published
Content linting (configurable + built-in rules)
Readme
Recheck - Content Linting Tool
A modern, production-ready content linter for markdown files with configurable rules and built-in content quality checks.
Features
✅ Modern Scope-Based Architecture
- File-first processing with semantic scope parsing
- Support for
sentence,paragraph,heading,code,default,raw, andallscopes - Vale-compatible scope notation (e.g.,
heading.h1,heading.h2) - Efficient rule indexing for fast processing at scale
✅ Flexible Configuration Format
- Modern
assertions-based rule definitions severitylevels:off,info,warn,error- Array-based scope targeting for precise control
- Comprehensive JSON Schema validation
✅ Production-Ready Engine
- High-performance JavaScript engine optimized for large repositories
- Successfully processes 300+ files with 1,000+ issues efficiently
- Built-in rules for common content quality checks
- Safe auto-fix capabilities for appropriate rules
✅ Developer-Friendly CLI
- Table, JSON, SARIF, and GitHub Actions output formats for CI/CD integration
- Universal output-path option for file export
- Inline PR annotations with GitHub Actions format
- Severity filtering and detailed statistics
- Auto-fix with granular control
- Comprehensive error reporting
Installation
# Navigate to the recheck package
cd packages/recheck
# Install dependencies
pnpm install
# Build the project
pnpm buildUsage
Validate Configuration
# Validate with explicit config file
node dist/cli.js validate --config recheck.example.yaml
# Auto-discover config file in current directory
node dist/cli.js validateRun content linting
# Run on current directory
node dist/cli.js run . --config recheck.example.yaml
# Run on specific file
node dist/cli.js run README.md --config recheck.example.yaml
# Filter by severity (only show errors)
node dist/cli.js run . --severity error
# Show all enabled rules (info and above)
node dist/cli.js run . --severity info
# Output formats (table is default)
node dist/cli.js run . --output table # Human-readable table (default)
node dist/cli.js run . --output json # Structured JSON for CI
node dist/cli.js run . --output sarif # SARIF format for security tools
node dist/cli.js run . --output github-actions # GitHub Actions annotations (inline PR comments)
# Show detailed statistics
node dist/cli.js run . --stats
# Auto-fix safe issues (trailing spaces, bullet style, hard tabs)
node dist/cli.js run . --fix
# Combine auto-fix with statistics
node dist/cli.js run . --fix --stats
# Limit annotations for CI (applies to file output, default: 20)
node dist/cli.js run . --annotations-limit 50
# Output to file (works with all formats)
node dist/cli.js run . --output json --output-path report.json
node dist/cli.js run . --output sarif --output-path recheck.sarif
node dist/cli.js run . --output json --output-path limited.json --annotations-limit 50
# Emit run summary to a file (json or text)
node dist/cli.js run . --summary json --summary-path recheck-summary.json
# Scan only changed files (via file list or stdin)
# From file:
node dist/cli.js run . --changed-only --changed-list changed.txt
# Or with stdin:
git diff --name-only origin/main... | node dist/cli.js run . --changed-onlyConfiguration Format
Configuration uses a modern assertions-based format with severity levels and flexible scope targeting:
recheck/us-spelling:
scope: all # default
severity: error
message: 'Use the US spelling "%s" instead of British "%s".'
link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words
appliesTo:
- "docs/**" # Only apply to documentation
assertions:
swap:
ignoreCase: true
wordBoundary: true
pairs:
color: colour
behavior: behaviour
organize: organise
exceptions:
files: [docs/style-guide.md]
lines:
- "British spellings such as 'color'"
recheck/no-gerund-headings:
severity: error
scope:
- heading.h1
- heading.h2
- heading.h3
message: 'Do not start headings with a gerund.'
excludes:
- "**/drafts/**" # Exclude draft documents
assertions:
pattern:
ignoreCase: true
tokens:
- '^\\w*ing.*'
recheck/config-line-length:
severity: error
message: 'Config docs: keep lines under %s characters.'
appliesTo:
- "docs/config/**" # Only apply to config documentation
assertions:
max-line-length:
max: 100
ignoreCodeBlocks: true
recheck/bullet-style-dash:
severity: error
message: "Use '-' for unordered list bullets."
autoFixable: true # Safe for auto-fix
excludes:
- "**/examples/**" # Allow mixed styles in examples
assertions:
bullet-style:
style: '-'
normalizeNested: trueExceptions
Rules can be configured with exceptions to skip specific files or lines:
File Exceptions
Skip entire files using glob patterns or exact matches:
recheck/us-spelling:
# ... other config
exceptions:
files:
- "docs/style-guide.md" # Exact filename
- "docs/api/*.md" # Glob pattern
- "**/CHANGELOG.md" # Recursive globFile matching supports:
- Basename matching:
style-guide.mdmatches any file with that name - Relative path matching:
docs/style-guide.mdmatches the specific path - Glob patterns:
docs/*.mdmatches all markdown files in docs directory
Line Exceptions
Skip specific lines using fragment matching:
recheck/no-trailing-spaces:
# ... other config
exceptions:
lines:
- "British spellings such as" # Fragment match
- "Code example:" # Beginning of line
- "// ignore-lint" # Comment-based exceptionLine matching behavior:
- Fragment matching: If the line contains the exception text anywhere, it's skipped
- Case-sensitive:
"Code Example"does not match"code example" - Multiple patterns: Any matching pattern will skip the line
Exception Examples
# Skip documentation style guides for spelling rules
recheck/us-spelling:
exceptions:
files: ["docs/style-guide.md", "**/*style*"]
lines: ["British spellings such as 'colour'"]
# Skip auto-generated files and code blocks
recheck/no-trailing-spaces:
exceptions:
files: ["**/generated/**", "CHANGELOG.md"]
lines: ["```", "Code example:", "// prettier-ignore"]Rule Types and Assertions
Assertion Types
Rules are defined using assertions that specify their behavior:
Swap Assertions (swap)
Text replacement with configurable options:
assertions:
swap:
ignoreCase: true
wordBoundary: true
pairs:
color: colour
behavior: behaviourPattern Assertions (pattern)
Regex-based pattern matching:
assertions:
pattern:
ignoreCase: true
tokens:
- '^\\w*ing.*'Built-in Assertions
Predefined content checks with typed options:
max-line-length- Line length enforcementno-trailing-spaces- Trailing whitespace detection ✅ Auto-fixablebullet-style- Unordered list bullet consistency ✅ Auto-fixablesemantic-line-breaks- Semantic line break validationno-hard-tabs- Hard tab detection ✅ Auto-fixableno-duplicate-headings- Duplicate heading detectionno-broken-fragment-links- Broken link fragment detection
Enhanced Scope Support
The scope field supports arrays and specific targeting:
scope: all # Apply to all content
scope: heading # Apply to all headings
scope: sentence # Apply to sentences only
scope: paragraph # Apply to paragraphs only
scope: code # Apply to code blocks only
scope: default # Apply to default content (excludes code/comments)
scope: raw # Apply to raw file content
scope: # Apply to specific heading levels
- heading.h1
- heading.h2
- heading.h3Rule Severity Levels
Rules can be configured with different severity levels:
off: Disable the rule completelyinfo: Informational messages (exit code 0)warn: Warning messages (exit code 0)error: Error messages (exit code 1)
Auto-Fix Safety
Only rules marked with autoFixable: true can be automatically corrected:
- ✅ Safe Rules:
no-trailing-spaces,bullet-style,no-hard-tabs - ❌ Unsafe Rules:
max-line-length,semantic-line-breaks,no-duplicate-headings
GitHub Actions Integration
Recheck provides seamless GitHub Actions integration for automated content quality checking on pull requests.
Output Format: github-actions
Use the --output github-actions format to generate inline file annotations that appear directly on pull request files:
# Basic GitHub Actions output
node dist/cli.js run docs --output github-actions
# With annotation limits (recommended for PR workflows)
node dist/cli.js run docs --output github-actions --annotations-limit 20Annotation Output
The GitHub Actions format produces annotations that GitHub automatically displays as inline comments:
::error title=recheck/no-trailing-spaces,file=docs/guide.md,line=42,col=15,endColumn=18::Remove trailing spaces.
::warning title=recheck/bullet-style-dash,file=docs/api.md,line=23,col=1,endColumn=2::Use '-' for unordered list bullets.GitHub Actions Limits
GitHub Actions has strict limits on annotations:
- 10 error and 10 warning annotations per step
- 50 total annotations per job
Recommendation: Use --annotations-limit 20 (the default) to stay well within these limits while prioritizing the most critical issues.
Workflow Example
- name: Run recheck with inline annotations
run: |
node packages/recheck/dist/cli.js run docs \
--config recheck.yaml \
--output github-actions \
--changed-only < changed-files.txtThis creates both inline file annotations AND summary comments when combined with the PR comment workflow.
Performance
The new architecture delivers excellent performance:
- ✅ Small Projects: ~15ms for single files
- ✅ Medium Projects: ~50-100ms for 10-50 files
- ✅ Large Projects: Successfully processes 300+ files with 1,000+ issues
- ✅ Scalable: File-first architecture with rule indexing optimizes for large repositories
Dependencies
Runtime Dependencies
ajv+ajv-formats- JSON Schema validationjs-yaml- YAML configuration parsingyargs- CLI interfacecolorette- Terminal colorspicomatch- File pattern matching
Development Dependencies
vitest- Modern testing frameworktypescript- Type checking and compilation@types/*- TypeScript definitions
Example Output
Standard Run
🏃 Running recheck on: docs/
✅ Configuration loaded successfully!
Config file: recheck.yaml
Loaded 8 rule(s)
Disabled 1 rule(s) (severity: off)
🔧 Running 8 rule(s)...
Found 311 markdown file(s)
Checking rule: us-spelling...
Checking rule: no-gerund-headings...
Checking rule: oxford-comma...
Checking rule: no-trailing-spaces...
Checking rule: bullet-style-dash...
Checking rule: semantic-line-breaks...
Checking rule: no-hard-tabs...
Checking rule: no-duplicate-headings...
📋 Found 1086 issue(s):
us-spelling README.md:68:5 Use the US spelling "color" instead of British "colour".
no-trailing-spaces README.md:15:42 Remove trailing spaces.
bullet-style-dash docs/guide.md:22:1 Use '-' for unordered list bullets.
65 error(s)
1021 warning(s)
❌ Found 65 error(s). Exiting with code 1.
Completed in 156msJSON Output
{
"summary": {
"filesScanned": 311,
"totalIssues": 1086,
"breakdown": {
"recheck/no-trailing-spaces": {
"errors": 65,
"warnings": 0,
"info": 0,
"total": 65
},
"recheck/bullet-style-dash": {
"errors": 1021,
"warnings": 0,
"info": 0,
"total": 1021
}
}
},
"issues": [
{
"file": "../../docs/public/branding/index.md",
"line": 13,
"column": 22,
"text": "Use the brand guidelines when applying Redocly brand",
"match": " ",
"ruleName": "recheck/no-trailing-spaces",
"severity": "error",
"message": "Remove trailing spaces."
}
]
}What's Working Now
- ✅ Modern Architecture: File-first processing with scope-based rule application
- ✅ Vale Compatibility: Scope notation compatible with Vale linter
- ✅ Swap Rules: Find and replace text patterns with word boundaries and case sensitivity
- ✅ Pattern Rules: Regex matching with precise scope filtering
- ✅ Built-in Rules: All 6 built-in rules fully implemented with comprehensive tests
- ✅ File Discovery: Recursive markdown file finding with common directory exclusions
- ✅ Multiple Output Formats: Human-readable table, structured JSON, SARIF, and GitHub Actions
- ✅ Severity Filtering: Show only errors, warnings, or all issues
- ✅ Exit Codes: Non-zero exit when errors found (perfect for CI)
- ✅ Exception Handling: Skip lines and files that match exception patterns
- ✅ Auto-Fix: Safe automatic correction for appropriate rules
- ✅ Production Scale: Successfully handles large documentation repositories
- ✅ Comprehensive Testing: Full test suite with 161 passing tests
Key Design Principles
- File-First Processing: Iterate by files, then by semantic scopes within files
- Scope-Based Rules: Apply rules only to relevant content scopes
- Type Safety: Full TypeScript coverage with strict typing
- Scope parsing: Efficient per-file segmentation for applying rules by scope
- Modular Rules: Each built-in rule in its own file with dedicated tests
- Safe Auto-Fix: Granular control over which rules can auto-fix
- Vale Compatibility: Scope notation compatible with existing Vale configurations
File Targeting
Rules can target specific files using path patterns with appliesTo and excludes:
Apply Rules to Specific Files
recheck/config-docs-only:
severity: error
message: "Config docs must follow specific patterns"
appliesTo:
- "docs/config/**" # All files in docs/config directory
- "**/api/*.md" # All .md files in any api directory
- "*.config.md" # Files ending with .config.md
assertions:
pattern:
tokens: ["TODO"]
recheck/api-standards:
severity: warn
message: "API docs need review"
appliesTo:
- "docs/api/**" # Target API documentation
- "**/endpoints/*.md" # Target endpoint documentation
assertions:
pattern:
tokens: ["DRAFT", "TBD"]Exclude Files from Rules
recheck/no-todos:
severity: error
message: "No TODOs allowed"
excludes:
- "docs/drafts/**" # Exclude all draft documents
- "**/temp*.md" # Exclude temporary files
- "README.md" # Exclude specific file
assertions:
pattern:
tokens: ["TODO"]Path Pattern Support
File targeting supports multiple pattern types:
- Full path patterns:
docs/config/**,src/components/*.md - Recursive patterns:
**/api/*.md,**/README.md - Basename patterns:
*.config.md,temp*.md(backward compatible) - Exact matches:
README.md,docs/guide.md
Pattern Matching Strategy
The enhanced pattern matching checks patterns against:
- Filename (
config.md) - for simple patterns - Relative path (
docs/config/settings.md) - for full path patterns - Path segments (
config/settings.md) - for partial path patterns
This allows flexible targeting while maintaining backward compatibility.
Contributing
Want to add new assertions or improve existing ones? Check out our Contributing Guide for:
- 🏗️ Architecture overview - How the centralized scoping system works
- 📝 Step-by-step guide - Create new assertions following best practices
- 🧪 Testing guidelines - Comprehensive test coverage examples
- ✅ Code standards - Follow our established conventions
- 🚀 Quick examples - Get started with working code templates
The guide covers our modern architecture where the runner handles scoping automatically, so your assertions can focus on their core logic without worrying about segment filtering or line number adjustments.
Future Enhancements
- Plugin System: Custom rule loading from external files/packages
- Configuration Inheritance: Config file discovery and inheritance
- Watch Mode: Real-time linting as files change
- IDE Integration: Language server protocol support
- Additional Scopes: Support for more Vale-compatible scopes
