{"id":31578354,"url":"https://github.com/open-technology-foundation/md2ansi.bash","last_synced_at":"2026-05-07T00:31:37.538Z","repository":{"id":317475408,"uuid":"1067558687","full_name":"Open-Technology-Foundation/md2ansi.bash","owner":"Open-Technology-Foundation","description":"A zero-dependency Bash implementation of md2ansi that converts Markdown to ANSI-colored terminal output.","archived":false,"fork":false,"pushed_at":"2025-10-01T04:21:09.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-01T06:09:56.202Z","etag":null,"topics":["bash","markdown","markdown-terminal"],"latest_commit_sha":null,"homepage":"https://yatti.id/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Open-Technology-Foundation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-01T03:17:40.000Z","updated_at":"2025-10-01T04:21:12.000Z","dependencies_parsed_at":"2025-10-01T06:10:20.961Z","dependency_job_id":"07239530-fbd0-449c-84b5-e51c5b9de392","html_url":"https://github.com/Open-Technology-Foundation/md2ansi.bash","commit_stats":null,"previous_names":["open-technology-foundation/md2ansi.bash"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Open-Technology-Foundation/md2ansi.bash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Fmd2ansi.bash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Fmd2ansi.bash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Fmd2ansi.bash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Fmd2ansi.bash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Open-Technology-Foundation","download_url":"https://codeload.github.com/Open-Technology-Foundation/md2ansi.bash/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Fmd2ansi.bash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278510917,"owners_count":25998997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","markdown","markdown-terminal"],"created_at":"2025-10-05T19:57:02.917Z","updated_at":"2026-05-07T00:31:37.530Z","avatar_url":"https://github.com/Open-Technology-Foundation.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MD2ANSI (Bash Implementation)\n\n![Version](https://img.shields.io/badge/version-1.0.1-blue.svg)\n![License](https://img.shields.io/badge/license-GPL--3.0-green.svg)\n![Shell](https://img.shields.io/badge/bash-5.2+-orange.svg)\n![Status](https://img.shields.io/badge/status-stable-brightgreen.svg)\n\nA **zero-dependency Bash implementation** of md2ansi that converts Markdown to ANSI-colored terminal output.\n\n## Overview\n\nThis is a pure Bash implementation of the md2ansi markdown-to-ANSI formatter, designed to be compatible with the [Python version](https://github.com/Open-Technology-Foundation/md2ansi) while following strict Bash coding standards. The implementation is completely self-contained in a single executable file with no external dependencies beyond standard POSIX tools.\n\n**Key Features:**\n- ✓ Zero installation dependencies\n- ✓ Single-file monolithic design\n- ✓ Full markdown support (headers, lists, tables, code blocks, formatting)\n- ✓ 256-color ANSI output\n- ✓ Syntax highlighting for Python, JavaScript, and Bash\n- ✓ Security features (file size limits, input sanitization, ReDoS protection)\n- ✓ Compatible with Python version's command-line interface\n- ✓ Browser-based markdown preview with pandoc (`mdview`)\n\n## Quick Start\n\n### Installation\n\n#### Quick Start (No Installation Required)\n\n```bash\n# Clone the repository\ngit clone https://github.com/Open-Technology-Foundation/md2ansi.bash.git\ncd md2ansi.bash\n\n# Make scripts executable\nchmod +x md2ansi md ansi-info md-link-extract mdview\n\n# Test it\nmd2ansi --version\nmd2ansi README.md\n```\n\n#### Method 1: Using Makefile (Recommended)\n\n**System-wide installation** (requires sudo):\n\n```bash\nmake install\n```\n\nThis installs to `/usr/local` by default:\n- Executables → `/usr/local/bin/`\n- Man page → `/usr/local/share/man/man1/`\n- Bash completion → `/usr/local/share/bash-completion/completions/`\n- mdview data → `/usr/local/share/mdview/` (config + themes)\n\n**User-local installation** (no sudo required):\n\n```bash\nmake install-local\n```\n\nThis installs to `~/.local`:\n- Executables → `~/.local/bin/`\n- Man page → `~/.local/share/man/man1/`\n- Bash completion → `~/.local/share/bash-completion/completions/`\n- mdview data → `~/.local/share/mdview/` (config + themes)\n\n**Custom installation prefix**:\n\n```bash\nmake install PREFIX=/opt/md2ansi\n```\n\n**Other Makefile targets**:\n\n```bash\nmake uninstall      # Remove installed files\nmake test          # Run shellcheck validation\nmake clean         # Remove temporary files\nmake help          # Show help message\n```\n\n#### Method 2: Manual Installation\n\nFor complete control over the installation:\n\n```bash\n# Install executables\nsudo install -m 0755 md2ansi /usr/local/bin/\nsudo install -m 0755 md /usr/local/bin/\nsudo install -m 0755 ansi-info /usr/local/bin/\nsudo install -m 0755 md-link-extract /usr/local/bin/\nsudo install -m 0755 mdview /usr/local/bin/\n\n# Install manpage\nsudo install -m 0644 md2ansi.1 /usr/local/share/man/man1/\nsudo mandb  # Update man database\n\n# Install bash completion\nsudo install -m 0644 md2ansi.bash_completion /usr/local/share/bash-completion/completions/md2ansi\n\n# Install mdview data (config + themes)\nsudo mkdir -p /usr/local/share/mdview/themes\nsudo install -m 0644 mdview.conf /usr/local/share/mdview/\nsudo install -m 0644 themes/*.css themes/*.theme /usr/local/share/mdview/themes/\n\n# Verify installation\nmd2ansi --version\nman md2ansi\n```\n\n#### Post-Installation\n\n**View the manual page:**\n\n```bash\nman md2ansi\n```\n\n**For user-local installation**, ensure `~/.local/bin` is in your PATH:\n\n```bash\nexport PATH=\"$HOME/.local/bin:$PATH\"\n```\n\nAdd to `~/.bashrc` or `~/.bash_profile` to make permanent.\n\n**Enable bash completion** (user-local only):\n\nAdd to `~/.bashrc`:\n\n```bash\nif [ -f ~/.local/share/bash-completion/completions/md2ansi ]; then\n  . ~/.local/share/bash-completion/completions/md2ansi\nfi\n```\n\n### Basic Usage\n\n```bash\n# View a markdown file\nmd2ansi README.md\n\n# With pagination (recommended for long files)\nmd README.md\n\n# Process from stdin\ncat README.md | md2ansi\necho \"# Hello **World**\" | md2ansi\n\n# Multiple files\nmd2ansi file1.md file2.md file3.md\n\n# Preview in browser (requires pandoc)\nmdview README.md\n\n# View the manual\nman md2ansi\n```\n\n### Common Use Cases\n\n```bash\n# Read documentation in color\nmd /usr/share/doc/bash/README\n\n# Preview your markdown before committing\nmd2ansi CHANGELOG.md | less -R\n\n# View remote markdown files\ncurl -s https://raw.githubusercontent.com/user/repo/main/README.md | md2ansi\n\n# Check how your documentation will render\n./md README.md\n```\n\n## Features\n\n### Fully Implemented\n\n**Headers** (H1-H6) with distinct color gradients\n- Bright yellow (H1) to dark gray (H6)\n- Inline formatting supported within headers\n\n**Inline Formatting:**\n- ✓ Bold (`**text**`)\n- ✓ Italic (`*text*`)\n- ✓ Combined bold+italic (`***text***`)\n- ✓ Strikethrough (`~~text~~`)\n- ✓ Inline code (`` `code` ``)\n- ✓ Links (`[text](url)`) with underline formatting\n- ✓ Images (`![alt](url)`) displayed as placeholders\n\n**Lists:**\n- ✓ Unordered lists (`-` or `*`)\n- ✓ Ordered lists (`1.`, `2.`, etc.)\n- ✓ Task lists (`- [ ]` and `- [x]`)\n- ✓ Nested lists with proper indentation\n- ✓ Inline formatting within list items\n\n**Tables:**\n- ✓ Pipe-delimited tables with alignment support\n- ✓ Left, center, and right alignment (`:---`, `:---:`, `---:`)\n- ✓ Inline formatting in cells\n- ✓ Proper borders and spacing\n- ✓ Auto-sizing columns\n\n**Code Blocks:**\n- ✓ Fenced code blocks (` ``` ` and `~~~`)\n- ✓ Syntax highlighting for Python, JavaScript, and Bash\n- ✓ Language detection and aliases (py, js, sh)\n- ✓ Comment and keyword highlighting\n\n**Additional Elements:**\n- ✓ Blockquotes (`\u003e`)\n- ✓ Horizontal Rules (`---`, `===`, `___`)\n- ✓ Footnotes (`[^1]` references and `[^1]: text` definitions)\n\n**Advanced Features:**\n- ✓ ANSI-aware text wrapping\n- ✓ Terminal width auto-detection\n- ✓ Feature toggles (--no-tables, --no-syntax-highlight, etc.)\n- ✓ Plain text mode for non-ANSI terminals\n- ✓ Debug mode with detailed traces\n\n**Security:**\n- ✓ File size limits (10MB maximum)\n- ✓ Input sanitization (ANSI escape removal)\n- ✓ ReDoS protection with timeout\n- ✓ Proper signal handling\n\n## Utility Scripts\n\n### `md` - Paginated Viewer\n\nThe `md` script wraps `md2ansi` output with `less` for comfortable viewing of long markdown files:\n\n```bash\nmd README.md              # View with pagination and color\nmd documentation/*.md     # Browse multiple files sequentially\n```\n\n**Features:**\n- Automatic pagination using `less -FXRS`\n- Auto-exit if content fits on one screen (-F)\n- No terminal initialization (-X)\n- Raw ANSI color support (-R)\n- No line wrapping (-S)\n\n**Usage:**\n- `SPACE` - Next page\n- `b` - Previous page\n- `q` - Quit\n- `/pattern` - Search\n- `n` - Next search result\n\n### `ansi-info` - ANSI Palette \u0026 Terminal Capability Report\n\nRenders a four-section report covering the full ANSI colour picture for the active terminal:\n\n```bash\nansi-info             # Display full report (paged via less -FXRS)\nansi-info | cat       # Dump raw escape codes (bypass pager)\n```\n\n**Sections:**\n\n1. **256-colour palette** — Standard 16 (0-15), 6×6×6 cube (16-231), and grayscale ramp (232-255), with `#RRGGBB` labels beneath every swatch.\n2. **SGR text attributes** — bold, dim, italic, underline, double-underline, blink, reverse, strike, overline, plus combined attribute+colour demos.\n3. **24-bit truecolor ramps** — red, green, blue, HSV hue sweep, and grayscale gradients via `\\e[38;2;R;G;Bm`.\n4. **Terminal capability footer** — named codes for indices 0-15, plus `TERM`, `COLORTERM`, `tput colors`, and truecolor detection.\n\n**Useful for:**\n- Verifying terminal 256-colour and truecolor support\n- Cross-referencing palette indices with hex/RGB values\n- Testing SGR attribute rendering\n- Diagnosing terminal capability mismatches\n\n### `md-link-extract` - Link Extractor\n\nExtract and list all URLs from markdown files:\n\n```bash\nmd-link-extract README.md              # Extract all links\nmd-link-extract docs/*.md | sort -u    # Deduplicated links from multiple files\nmd-link-extract *.md | wc -l          # Count total links\n```\n\n**Features:**\n- ✓ Extracts inline links `[text](url)`\n- ✓ Extracts bare URLs `\u003chttp://example.com\u003e`\n- ✓ Extracts reference-style links `[text][ref]`\n- ✓ Automatic URL deduplication\n- ✓ One URL per line for easy processing\n\n**Use cases:**\n- Link validation before publishing\n- Finding broken documentation links\n- Creating link inventories\n- SEO analysis\n\n### `mdview` - Browser-Based Markdown Preview\n\nView markdown files as styled HTML in a browser window. Converts markdown via pandoc with configurable themes and syntax highlighting:\n\n```bash\nmdview README.md                          # Open in browser with default theme\nmdview --theme github-dark doc.md         # Specify theme\nmdview --window-size 1200x900 README.md   # Custom browser window size\nmdview --browser /usr/bin/firefox doc.md  # Override browser\n```\n\n**Requires:** `pandoc` (the only external dependency in the project)\n\n**Features:**\n- Recursive inter-file link resolution (`.md` links rewritten to `.html`)\n- [← Back] navigation links on child pages\n- Automatic browser detection (Google Chrome, Chromium, or xdg-open fallback)\n- Configurable themes via CSS + highlight-style pairs\n- XDG-compliant configuration hierarchy\n- Safe for sourcing as a Bash library (`source mdview`)\n- Scaled temp file cleanup (30s base + 2s per converted file; or `--preserve-tmp`)\n- `--app` mode for Chrome/Chromium (clean window without browser chrome)\n\n**Configuration:**\n\n| Level | Config File | Theme Directory |\n|:------|:------------|:----------------|\n| System | `\u003cprefix\u003e/share/mdview/mdview.conf` | `\u003cprefix\u003e/share/mdview/themes/` |\n| User | `${XDG_CONFIG_HOME:-~/.config}/mdview/mdview.conf` | `${XDG_DATA_HOME:-~/.local/share}/mdview/themes/` |\n\nPrecedence: CLI flags \u003e user config \u003e system config \u003e defaults\n\nEach theme requires two files: `\u003cname\u003e.css` (page styling) and `\u003cname\u003e.theme` (pandoc syntax highlight style).\n\n**Options:**\n\n| Option | Description | Default |\n|:-------|:------------|:--------|\n| `-t, --theme NAME` | Theme name | `github-dark` |\n| `-s, --window-size WxH` | Browser window dimensions | `960x1080` |\n| `-b, --browser PATH` | Browser executable | auto-detect |\n| `-P, --preserve-tmp` | Keep session directory and print its path | |\n| `-V, --version` | Show version | |\n| `-h, --help` | Show help | |\n\n**Sourced mode:**\n\n```bash\nsource mdview           # Import mdview() function\nmdview README.md        # Call directly\n```\n\nWhen sourced, `mdview` does not impose `set -e` or modify the caller's shell traps.\n\n## Command-Line Options\n\n### Basic Options\n\n```bash\n# Show help\nmd2ansi --help\nmd2ansi -h\n\n# Show version\nmd2ansi --version\nmd2ansi -V\n\n# Enable debug mode (output to stderr)\nmd2ansi --debug README.md 2\u003edebug.log\nmd2ansi -D file.md\n\n# Force specific terminal width\nmd2ansi --width 100 README.md\nmd2ansi -w 80 file.md\n\n# Plain text mode (all formatting disabled)\nmd2ansi --plain README.md\nmd2ansi -t file.md\n```\n\n### Feature Toggles\n\nSelectively disable specific features:\n\n```bash\n# Disable table formatting\nmd2ansi --no-tables doc.md\n\n# Disable syntax highlighting\nmd2ansi --no-syntax-highlight code-heavy.md\n\n# Disable footnotes\nmd2ansi --no-footnotes academic.md\n\n# Disable task lists (checkboxes)\nmd2ansi --no-task-lists todo.md\n\n# Disable image placeholders\nmd2ansi --no-images doc.md\n\n# Disable link formatting\nmd2ansi --no-links plain.md\n\n# Combine multiple toggles\nmd2ansi --no-tables --no-syntax-highlight --no-footnotes simple.md\n```\n\n### Examples with Options\n\n```bash\n# Process file with custom width for narrow terminals\nmd2ansi -w 60 README.md\n\n# Debug table parsing issues\nmd2ansi -D tables.md 2\u003e\u00261 | grep -i table\n\n# Plain mode for piping to log files\nmd2ansi --plain CHANGELOG.md \u003e\u003e release-notes.txt\n\n# Disable heavy features for faster processing\nmd2ansi --no-syntax-highlight --no-tables large-file.md\n```\n\n## Expanded Examples\n\n### Headers and Formatting\n\n**Input:**\n```markdown\n# Main Title\n## Subtitle\n### Section Header\n\nThis is **bold**, *italic*, and ***bold italic*** text.\n\nThis is ~~strikethrough~~ and `inline code`.\n\nVisit [GitHub](https://github.com) for more.\n```\n\n**Command:**\n```bash\necho \"...\" | md2ansi\n```\n\n**Result:** Colored terminal output with distinct header colors, formatted text, and underlined links.\n\n### Lists and Task Lists\n\n**Input:**\n```markdown\nShopping List:\n- Apples\n- Oranges\n  - Valencia oranges\n  - Blood oranges\n- Bananas\n\nTodo:\n- [x] Write documentation\n- [ ] Add tests\n- [ ] Review code\n```\n\n**Command:**\n```bash\nmd2ansi shopping.md\n```\n\n**Result:** Nested bullets with proper indentation, checked and unchecked task boxes.\n\n### Tables with Alignment\n\n**Input:**\n```markdown\n| Feature | Status | Priority |\n|:--------|:------:|---------:|\n| Headers | ✓      | High     |\n| Tables  | ✓      | Medium   |\n| Code    | ✓      | High     |\n```\n\n**Command:**\n```bash\nmd2ansi features.md\n```\n\n**Result:** Bordered table with left, center, and right aligned columns.\n\n### Code Blocks with Syntax Highlighting\n\n**Input:**\n````markdown\n```python\ndef fibonacci(n):\n    if n \u003c= 1:\n        return n\n    return fibonacci(n-1) + fibonacci(n-2)\n```\n````\n\n**Command:**\n```bash\nmd2ansi code-example.md\n```\n\n**Result:** Color-highlighted Python code with keywords, functions, and comments colored appropriately.\n\n### Blockquotes\n\n**Input:**\n```markdown\n\u003e This is a blockquote.\n\u003e It can span multiple lines.\n\u003e\n\u003e It can even have multiple paragraphs.\n```\n\n**Command:**\n```bash\nmd2ansi quote.md\n```\n\n**Result:** Indented quoted text with distinct background color.\n\n### Footnotes\n\n**Input:**\n```markdown\nThis statement needs a citation[^1].\n\nAnother fact[^2] worth noting.\n\n[^1]: Source: Academic Journal, 2024\n[^2]: See documentation for details\n```\n\n**Command:**\n```bash\nmd2ansi academic.md\n```\n\n**Result:** Footnote references inline, definitions rendered at bottom of document.\n\n### Real-World Usage\n\n```bash\n# Preview your project README\nmd README.md\n\n# Check documentation before deployment\nfind ./docs -name \"*.md\" -exec md {} \\;\n\n# View system documentation in color\nmd /usr/share/doc/bash/README\n\n# Quick reference for command output\nman bash | col -b \u003e bash.txt \u0026\u0026 md bash.txt\n\n# Compare markdown rendering\ndiff \u003c(md2ansi version1.md) \u003c(md2ansi version2.md)\n```\n\n## Comparison Table\n\n### vs Python md2ansi\n\n| Aspect | Bash Version | Python Version | Notes |\n|:-------|:-------------|:---------------|:------|\n| **Installation** | Copy one file | `pip install` | Bash: zero dependencies |\n| **Startup Time** | ~50ms | ~30ms | Bash slightly slower |\n| **Processing Speed** | 2-3x slower | Baseline | Python faster for large files |\n| **File Size** | 1,430 lines (42KB) | ~800 lines | Bash more verbose (md2ansi only) |\n| **Dependencies** | None (coreutils only) | Python 3.7+ | Bash more portable |\n| **Design** | Monolithic single file | Single module | Both self-contained |\n| **Features** | 100% compatible | Full feature set | Identical CLI |\n| **Syntax Highlighting** | Line-based regex | Token-based parser | Python more sophisticated |\n| **Error Handling** | `set -e` + trap | try/except | Different paradigms |\n| **ReDoS Protection** | `timeout` command | multiprocessing | Different approaches |\n| **Memory Usage** | Very low | Low | Both efficient |\n| **Platform** | Linux/Unix/macOS | Cross-platform | Python more portable |\n| **Security** | Built-in limits | Built-in limits | Equivalent protection |\n\n**Recommendation:**\n- **Use Bash version**: Quick installation, zero dependencies, system integration\n- **Use Python version**: Larger files (\u003e5MB), complex syntax highlighting, Windows support\n\n### vs Other Markdown Renderers\n\n| Feature | md2ansi.bash | bat | glow | mdcat | rich |\n|:--------|:-------------|:----|:-----|:------|:-----|\n| **Zero Install** | ✓ | ✗ | ✗ | ✗ | ✗ |\n| **Dependencies** | None | Rust | Go | Rust | Python |\n| **Tables** | ✓ | ✗ | ✓ | ✓ | ✓ |\n| **Syntax Highlight** | Basic | ✓✓ | ✓ | ✓ | ✓✓ |\n| **Footnotes** | ✓ | ✗ | ✗ | ✗ | ✓ |\n| **File Size** | 45KB | ~5MB | ~10MB | ~2MB | varies |\n| **Startup** | 50ms | 100ms | 200ms | 80ms | 150ms |\n| **Portable** | ✓✓ | ✓ | ✓ | ✓ | ✓ |\n| **Customizable** | ✓ | ✓✓ | ✓ | ✓ | ✓✓ |\n\n**md2ansi.bash advantages:**\n- Truly zero dependencies (only coreutils)\n- Single file deployment\n- Full markdown spec support\n- Footnote support\n- Smallest file size\n- Fast startup\n\n**When to use alternatives:**\n- **bat**: Need advanced syntax highlighting, line numbers, git integration\n- **glow**: Want TUI navigation, emoji support, glamorous styling\n- **mdcat**: Need image rendering in iTerm2/Kitty\n- **rich**: Python ecosystem integration, complex formatting\n\n## Architecture\n\n### Design Philosophy\n\nmd2ansi follows a **monolithic single-file design** for maximum portability and zero installation friction. All core functionality is embedded in one executable file (`md2ansi`, 1,430 lines) with no external libraries or modules. The `mdview` browser preview utility (299 lines) is a separate companion script.\n\n**Design Benefits:**\n\n| Benefit | Description |\n|:--------|:------------|\n| **Zero Installation Issues** | No broken paths, missing dependencies, or version conflicts |\n| **Single File Deployment** | Copy to `/usr/local/bin/` and it works immediately |\n| **Faster Startup** | No overhead from sourcing multiple files (~50ms) |\n| **Simpler Debugging** | All code in one place for easy tracing and modification |\n| **Clean Architecture** | Well-organized internal sections with clear markers |\n| **Maximum Portability** | Works on any system with Bash 5.2+ and coreutils |\n\n### Project Structure\n\n```\nmd2ansi.bash/\n├── md2ansi               # Main executable (1,430 lines, 42KB)\n│                         # ◉ All functionality in single file\n├── md2ansi.bash          # Symlink → md2ansi\n├── md                    # Pagination wrapper (15 lines)\n├── ansi-info             # ANSI palette + terminal capability report (306 lines)\n├── md-link-extract       # Link extractor (66 lines)\n├── mdview                # Browser-based markdown preview (299 lines)\n├── mdview.conf           # Default mdview configuration\n├── rewrite-md-links.lua  # Pandoc Lua filter: .md → .html link rewriting\n├── themes/               # mdview theme files\n│   ├── github-dark.css   # Page styling (dark theme)\n│   ├── github-dark.theme # Pandoc syntax highlight style (dark)\n│   ├── github-light.css  # Page styling (light theme)\n│   └── github-light.theme # Pandoc syntax highlight style (light)\n├── md2ansi.1             # Man page\n├── md2ansi.bash_completion # Bash completion (195 lines)\n├── Makefile              # Build/install targets\n├── LICENSE               # GPL-3.0 license\n├── README.md             # This file\n└── test/\n    ├── run_tests         # Test suite runner (181 lines)\n    ├── test_basic.sh     # Basic features (128 lines)\n    ├── test_code.sh      # Code blocks (168 lines)\n    ├── test_edge_cases.sh # Edge cases (208 lines)\n    ├── test_footnotes.sh # Footnotes (105 lines)\n    ├── test_gaps.sh      # Audit gap coverage (163 lines)\n    ├── test_mdview.sh    # mdview utility tests (173 lines)\n    ├── test_options.sh   # Feature toggles (96 lines)\n    ├── test_security.sh  # Security features (133 lines)\n    ├── test_tables.sh    # Tables (96 lines)\n    └── test_wrapping.sh  # Text wrapping (182 lines)\n```\n\n**Total Project Size:**\n- Main executable: 1,430 lines\n- Utility scripts: 686 lines (md, ansi-info, md-link-extract, mdview)\n- Test suite: 1,633 lines\n- **Total: 3,749 lines**\n\n### Internal Code Organization\n\nThe `md2ansi` script is organized into clearly marked sections:\n\n| Section | Lines | Purpose |\n|:--------|:------|:--------|\n| **Script Header** | 1-35 | Shebang, strict mode, metadata, global variables, state tracking |\n| **Utility Functions** | 36-172 | Messaging, terminal detection, file validation, signal handling, string manipulation |\n| **ANSI Color Definitions** | 173-269 | Color constants, ANSI escape sequences, color detection, strip/sanitize functions |\n| **Rendering Functions** | 270-655 | Bold, italic, strikethrough, links, inline code, text wrapping, header/list/blockquote rendering |\n| **Table Rendering Functions** | 656-961 | Table parsing, alignment detection, column width calculation, table output rendering |\n| **Markdown Parser Functions** | 962-1204 | Main parser, code blocks, tables, headers, lists, footnotes, regular text processing |\n| **Main Script Functions** | 1205-1430 | Argument parsing, file processing, main entry point, program invocation |\n\nEach section is marked with clear header comments:\n```bash\n# ================================================================================\n# ANSI Color Definitions\n# ================================================================================\n```\n\n### State Management\n\n**Global State Variables:**\n\n```bash\n# Configuration\nTERM_WIDTH=0              # Auto-detected terminal width\nMAX_FILE_SIZE=10485760    # 10MB file size limit\n\n# Feature Flags\nOPTIONS[footnotes]=1\nOPTIONS[syntax_highlight]=1\nOPTIONS[tables]=1\nOPTIONS[task_lists]=1\nOPTIONS[images]=1\nOPTIONS[links]=1\n\n# Parsing State\nIN_CODE_BLOCK=0           # Are we inside a code fence?\nCODE_FENCE_TYPE=''        # ``` or ~~~\nCODE_LANG=''              # Language identifier\nFOOTNOTES=()              # Associative array of footnote definitions\nFOOTNOTE_REFS=()          # Array tracking footnote reference order\n```\n\n### Key Functions\n\n**Core Processing Pipeline:**\n1. `main()` - Entry point, argument parsing\n2. `process_file()` - Read file/stdin into line array\n3. `parse_markdown()` - Main parsing loop (block-level)\n4. `colorize_line()` - Inline formatting (bold, italic, links)\n5. `wrap_text()` - ANSI-aware text wrapping\n6. Output to stdout\n\n**Rendering Functions:**\n- `render_header()` - H1-H6 with color gradients\n- `render_list_item()` - Unordered lists\n- `render_ordered_item()` - Numbered lists\n- `render_task_item()` - Checkboxes\n- `render_table()` - Complete table parsing and rendering\n- `render_code_line()` - Code with syntax highlighting\n- `render_blockquote()` - Quoted text\n- `render_hr()` - Horizontal rules\n- `render_footnotes()` - Footnote section at end\n\n## Testing\n\n### Test Suite\n\nThe project includes a comprehensive test suite with 10 test files covering all features:\n\n| Test File | Lines | Coverage |\n|:----------|:------|:---------|\n| **run_tests** | 181 | Test runner with assertion framework |\n| **test_basic.sh** | 128 | Headers, inline formatting, lists, links, images, horizontal rules |\n| **test_code.sh** | 168 | Fenced code blocks, syntax highlighting, language detection, code fence types |\n| **test_edge_cases.sh** | 208 | Empty files, malformed input, edge cases, error handling |\n| **test_footnotes.sh** | 105 | Footnote references, definitions, ordering, missing definitions |\n| **test_gaps.sh** | 163 | Audit gap coverage, combined flag parsing, fence mismatch handling |\n| **test_mdview.sh** | 173 | mdview CLI options, argument validation, sourced mode, full pipeline |\n| **test_options.sh** | 96 | Feature toggles, --no-* options, plain mode, option combinations |\n| **test_security.sh** | 133 | File size limits, line length limits, input sanitization, ReDoS protection |\n| **test_tables.sh** | 96 | Table parsing, alignment (left/center/right), borders, inline formatting in cells |\n| **test_wrapping.sh** | 182 | Text wrapping, ANSI-aware wrapping, terminal width handling |\n\n**Total test coverage: 1,633 lines**\n\n### Running Tests\n\n```bash\n# Run complete test suite\n./test/run_tests\n\n# Run individual test files\n./test/test_basic.sh\n./test/test_code.sh\n./test/test_edge_cases.sh\n./test/test_footnotes.sh\n./test/test_gaps.sh\n./test/test_mdview.sh\n./test/test_options.sh\n./test/test_security.sh\n./test/test_tables.sh\n./test/test_wrapping.sh\n```\n\n### Test Framework\n\nThe test suite uses a simple assertion-based framework:\n\n```bash\n# Example assertions\nassert_equals \"expected\" \"actual\" \"test name\"\nassert_contains \"haystack\" \"needle\" \"test name\"\nassert_not_empty \"$value\" \"test name\"\nassert_exit_code 0 \"command\" \"test name\"\n```\n\n### Manual Testing\n\n```bash\n# Test basic rendering\necho \"# Test\\n\\nThis is **bold** text.\" | ./md2ansi\n\n# Test with real README\n./md README.md\n\n# Test color support\n./ansi-info\n\n# Test link extraction\n./md-link-extract README.md\n\n# Test browser preview (requires pandoc)\n./mdview README.md\n\n# Test with debug output\n./md2ansi -D README.md 2\u003edebug.log\ncat debug.log\n\n# Test different terminal widths\n./md2ansi -w 60 README.md\n./md2ansi -w 120 README.md\n\n# Test feature toggles\n./md2ansi --no-tables --no-syntax-highlight README.md\n./md2ansi --plain README.md\n```\n\n## Development\n\n### Code Standards\n\nThis implementation strictly adheres to the Bash Coding Standard:\n\n| Standard | Implementation |\n|:---------|:---------------|\n| **Error Handling** | `set -euo pipefail` at start |\n| **Shell Options** | `shopt -s inherit_errexit shift_verbose extglob nullglob` |\n| **Indentation** | 2 spaces throughout (no tabs) |\n| **Variables** | Type-specific declarations (`declare -i`, `declare -a`, `declare -A`) |\n| **Constants** | `readonly` for immutable values |\n| **Scoping** | `local` for all function variables |\n| **Conditionals** | `[[ ]]` for tests, `(( ))` for arithmetic |\n| **Quoting** | All variable expansions quoted (except in `[[ ]]` or `(( ))`) |\n| **Messaging** | Standard functions: `error`, `warn`, `info`, `debug`, `die` |\n| **Cleanup** | Signal handling with `trap` |\n| **EOF Marker** | All scripts end with `#fin` followed by blank line |\n| **Increment** | Standalone `var+=1` — never `((var++))` or `((var+=1))` |\n\n### Adding New Features\n\nSince md2ansi is monolithic, all edits are made to the single `md2ansi` file.\n\n**To add inline formatting:**\n\nEdit the `colorize_line()` function in the Rendering Functions section:\n\n```bash\n# Example: Add underline support for __text__\nsed -E \"s/__([^_]+)__/${ANSI_UNDERLINE}\\1${ANSI_RESET}/g\"\n```\n\n**To add block-level elements:**\n\nEdit the `parse_markdown()` function in the Markdown Parser Functions section:\n\n```bash\n# Example: Add definition lists\nif [[ $line =~ ^:\\ (.*)$ ]]; then\n  render_definition \"${BASH_REMATCH[1]}\"\n  continue\nfi\n```\n\n**To add syntax highlighting for new language:**\n\nEdit the `render_code_line()` and add a highlighting function:\n\n```bash\nhighlight_ruby() {\n  local -- code=\"$1\"\n  # Add Ruby-specific patterns\n  sed -E \"s/\\b(def|class|end|if|else)\\b/${COLOR_KEYWORD}\\1${COLOR_CODEBLOCK}/g\" \u003c\u003c\u003c\"$code\"\n}\n```\n\n### Debug Mode\n\n```bash\n# Enable debug output (to stderr)\n./md2ansi -D file.md 2\u003edebug.log\n\n# View debug output\ncat debug.log\n\n# Real-time debug viewing\n./md2ansi -D file.md 2\u003e\u00261 | grep DEBUG\n\n# Debug specific features\n./md2ansi -D tables.md 2\u003e\u00261 | grep -i table\n```\n\n**Debug output includes:**\n- ◉ Terminal width detection\n- ◉ File size validation\n- ◉ Table parsing steps (column count, alignment)\n- ◉ Regex operation timeouts\n- ◉ Feature flag states\n\n### Code Review Checklist\n\nBefore submitting changes:\n\n- [ ] Follows Bash Coding Standard strictly\n- [ ] All variables properly declared with types (`declare -i`, `declare -a`, etc.)\n- [ ] Functions use `local` for all variables\n- [ ] No shellcheck warnings (`shellcheck md2ansi`)\n- [ ] Proper error handling with meaningful exit codes\n- [ ] Scripts end with `#fin` marker\n- [ ] Comments for complex logic\n- [ ] Test coverage for new features\n- [ ] Documentation updated in README\n- [ ] No performance regressions\n\n## Performance\n\n### Benchmarks\n\n| File Size | Processing Time | Notes |\n|:----------|:----------------|:------|\n| Small (\u003c10KB) | ~100ms | ◉ Fast, instant feedback |\n| Medium (100KB) | ~500ms | ◉ Good, responsive |\n| Large (1MB) | ~3-5s | ◉ Acceptable for terminal viewing |\n| Very Large (5-10MB) | ~15-30s | ◉ Slow but within limits |\n\n**Optimization target:** Terminal viewing responsiveness, not batch processing speed.\n\n### Performance Characteristics\n\n| Metric | Value | Notes |\n|:-------|:------|:------|\n| **Startup time** | ~50ms | Single-file load, no library sourcing |\n| **Processing speed** | ~2-3x slower than Python | Acceptable for terminal use |\n| **Memory usage** | Very low | Efficient line-by-line processing |\n| **File size limit** | 10MB | Configurable via `MAX_FILE_SIZE` |\n| **Terminal width** | 20-500 columns | Bounds checking |\n\n### Comparison to Python Version\n\nFor reference, processing a 1MB markdown file:\n- **Python version:** ~2 seconds\n- **Bash version:** ~5 seconds\n- **Difference:** Acceptable for interactive terminal use\n\n**Optimization notes:**\n- Single `sed` invocation with multiple patterns in `colorize_line()`\n- Minimal subprocess spawning\n- Efficient regex patterns\n- ANSI-aware text wrapping without repeated strip operations\n\n## Security Features\n\n| Feature | Implementation | Limit/Behavior |\n|:--------|:---------------|:---------------|\n| **File Size Limits** | Pre-processing validation with `wc -c` | 10MB maximum (configurable) |\n| **Input Sanitization** | ANSI escape sequence removal | All input cleaned via `strip_ansi()` |\n| **ReDoS Protection** | `timeout` command wrapper for regex | 1 second timeout on complex patterns |\n| **Injection Prevention** | Proper variable quoting throughout | All expansions quoted |\n| **Signal Handling** | `trap` cleanup handlers | Graceful Ctrl-C, proper exit |\n| **Bounds Checking** | Terminal width validation | 20-500 column range |\n| **Directory Protection** | Explicit file checks | Rejects directories |\n| **Permission Checks** | Read permission validation | Clear error messages |\n\n### Security Best Practices\n\n```bash\n# File size is checked before processing\nvalidate_file_size \"$filepath\" \"$MAX_FILE_SIZE\"\n\n# Input is sanitized\ncode=$(sanitize_ansi \"$code\")\n\n# Complex regex uses timeout\ntimeout 1 sed \"s/$pattern/$replacement/g\" \u003c\u003c\u003c\"$text\"\n\n# All variables are quoted\nprintf '%s\\n' \"$variable\"\n\n# Signal handlers ensure cleanup\ntrap 'cleanup $?' EXIT\ntrap 'cleanup 130' INT\n```\n\n## FAQ\n\n### General Usage\n\n**Q: Why use md2ansi.bash instead of the Python version?**\n\nA: The Bash version has zero installation dependencies and can be deployed as a single file. Perfect for system integration, minimal environments, or when you can't install Python packages.\n\n**Q: Will this work on macOS?**\n\nA: Yes, as long as you have Bash 5.2+ installed. macOS ships with Bash 3.2, so install via `brew install bash`.\n\n**Q: Can I use this in scripts and automation?**\n\nA: Absolutely. Use `--plain` mode for log files, or pipe to `less -R` for interactive viewing.\n\n**Q: How do I check if my terminal supports 256 colors?**\n\nA: Run `tput colors`. Should return 256 or higher. Also try `./ansi-info` to see all colors.\n\n### Troubleshooting\n\n**Q: Colors not showing?**\n\nA: Check terminal color support: `tput colors` (should be ≥256). Try setting `TERM=xterm-256color`.\n\n**Q: Script not found error?**\n\nA: Make sure you're in the repository directory or use the full path. Check that scripts are executable: `chmod +x md2ansi md`.\n\n**Q: Permission denied error?**\n\nA: Run `chmod +x md2ansi md ansi-info md-link-extract mdview` to make scripts executable.\n\n**Q: Output is garbled?**\n\nA: Your terminal may not support ANSI codes. Use `--plain` mode: `md2ansi --plain file.md`.\n\n**Q: Tables not rendering correctly?**\n\nA: Check that your table has proper alignment row (second row with `---`, `:---:`, `---:`). Or disable tables: `--no-tables`.\n\n**Q: Slow performance on large files?**\n\nA: For files \u003e5MB, consider using the Python version. Or disable heavy features: `--no-syntax-highlight --no-tables`.\n\n### Features\n\n**Q: Can I customize the colors?**\n\nA: Yes, edit the ANSI color constants in the `md2ansi` file (lines 227-322). Look for `COLOR_H1`, `COLOR_KEYWORD`, etc.\n\n**Q: Does it support GitHub-flavored markdown?**\n\nA: Most GFM features are supported: tables, task lists, strikethrough, fenced code blocks. Some advanced features (e.g., emoji shortcodes) are not implemented.\n\n**Q: Can I add syntax highlighting for other languages?**\n\nA: Yes, add a `highlight_\u003clanguage\u003e()` function in the Inline Rendering section and update the language case statement in `render_code_line()`.\n\n**Q: What about nested formatting like bold italic in tables?**\n\nA: Supported. Inline formatting works within table cells, list items, headers, and blockquotes.\n\n**Q: Can I process from a URL?**\n\nA: Yes, pipe from `curl`: `curl -s https://example.com/file.md | md2ansi`\n\n### Development\n\n**Q: How do I run the test suite?**\n\nA: Run `./test/run_tests` from the project directory. Individual tests can be run directly: `./test/test_basic.sh`.\n\n**Q: How do I contribute?**\n\nA: Follow the Bash Coding Standard strictly, run `shellcheck`, add tests, and update documentation.\n\n**Q: Why monolithic instead of modular?**\n\nA: Zero installation friction. One file to copy, no broken dependencies. The code is still well-organized with clear section markers.\n\n**Q: Can I use this as a library?**\n\nA: `md2ansi` is designed as a standalone executable, but you can source it and call `parse_markdown` directly if needed. The `mdview` utility is explicitly designed to work in both script and sourced modes.\n\n## Known Limitations\n\n| Limitation | Impact | Workaround |\n|:-----------|:-------|:-----------|\n| **Syntax Highlighting** | Simpler than Python (line-based vs token-based) | Use Python version for complex code |\n| **Unicode Width** | Depends on terminal Unicode support | Ensure UTF-8 terminal locale |\n| **Performance** | ~2-3x slower than Python for large files | Use Python version for files \u003e5MB |\n| **Nested Formatting** | Some edge cases may render differently | Test with actual content |\n| **Windows Support** | Requires WSL or Cygwin | Use Python version on native Windows |\n| **Emoji Rendering** | No emoji shortcode expansion | Use actual emoji characters |\n| **Math Rendering** | No LaTeX/MathJax support | Not planned for terminal renderer |\n\n## Contributing\n\n### Contribution Guidelines\n\n| Requirement | Tool/Process |\n|:------------|:-------------|\n| **Code Style** | Follow Bash Coding Standard strictly |\n| **Linting** | Run `shellcheck -x md2ansi md ansi-info md-link-extract mdview test/*.sh` with zero warnings |\n| **Testing** | Add tests for new features, all tests must pass |\n| **Compatibility** | Maintain CLI compatibility with Python version |\n| **Documentation** | Update README for new features, keep accurate |\n| **Performance** | No regressions, benchmark large files if changing parser |\n\n### Development Workflow\n\n```bash\n# 1. Make changes to code\nvim md2ansi\n\n# 2. Run shellcheck (must pass with zero warnings)\nshellcheck -x md2ansi md ansi-info md-link-extract mdview test/*.sh\n\n# 3. Run test suite (all tests must pass)\n./test/run_tests\n\n# 4. Test manually with real files\n./md README.md\n./md2ansi -D test-file.md 2\u003edebug.log\n\n# 5. Commit changes\ngit add md2ansi test/*.sh README.md\ngit commit -m \"Add feature: description\"\ngit push\n```\n\n### Code Review Requirements\n\nAll changes must:\n- ✓ Follow Bash Coding Standard\n- ✓ Pass shellcheck with zero warnings\n- ✓ Pass all existing tests\n- ✓ Include new tests for new features\n- ✓ Update README documentation\n- ✓ Use proper variable declarations and quoting\n- ✓ Include error handling with meaningful messages\n- ✓ End with `#fin` marker\n\n## External Tools Used\n\nAll tools are standard and available on any modern Linux/Unix system:\n\n| Tool | Package | Purpose |\n|:-----|:--------|:--------|\n| `tput` | ncurses | Terminal capability detection, color support |\n| `wc` | coreutils | File size validation |\n| `sed` | coreutils | Regex substitution for formatting |\n| `awk` | coreutils | Text processing (minimal usage) |\n| `grep` | coreutils | Pattern matching (minimal usage) |\n| `timeout` | coreutils | ReDoS protection wrapper |\n| `less` | util-linux | Pagination in `md` wrapper |\n| `stty` | coreutils | Terminal size detection fallback |\n| `pandoc` | pandoc | Markdown-to-HTML conversion (`mdview` only) |\n\n**Zero additional dependencies** for `md2ansi`, `md`, `ansi-info`, and `md-link-extract` — only standard POSIX/GNU utilities.\n\nThe `mdview` utility additionally requires `pandoc` for HTML conversion. All other tools are installed by default on Linux, macOS (with Homebrew), and BSD systems.\n\n## License\n\n**GPL-3.0** - Same as parent Python project\n\nSee [LICENSE](LICENSE) file for full text.\n\n## Acknowledgments\n\n- Based on the [Python md2ansi](https://github.com/Open-Technology-Foundation/md2ansi) implementation\n- Designed for maximum portability and zero dependencies\n- Built with readability and maintainability in mind\n\n## Project Statistics\n\n| Metric | Value |\n|:-------|:------|\n| **md2ansi Lines** | 1,430 lines (42KB) |\n| **Total Scripts** | 5 main + 1 test runner + 10 test files |\n| **Test Coverage** | 1,633 lines across 10 test files |\n| **Total Project** | 3,749 lines |\n| **Features** | 15+ markdown elements |\n| **Dependencies** | 0 (zero) |\n| **Installation** | Single file copy (md2ansi); mdview adds themes |\n| **Architecture** | Monolithic single-file design |\n| **Languages Highlighted** | Python, JavaScript, Bash |\n| **Security Features** | 7+ protections |\n\n---\n\n## Support \u0026 Links\n\n- **Repository**: https://github.com/Open-Technology-Foundation/md2ansi.bash\n- **Issues**: https://github.com/Open-Technology-Foundation/md2ansi.bash/issues\n- **Python Version**: https://github.com/Open-Technology-Foundation/md2ansi\n- **License**: GPL-3.0\n\n---\n\n**Status**: ✓ Core implementation complete and functional\n\n**Version**: 1.0.1\n\n#fin\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-technology-foundation%2Fmd2ansi.bash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-technology-foundation%2Fmd2ansi.bash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-technology-foundation%2Fmd2ansi.bash/lists"}