russross/blackfriday
Blackfriday: a markdown processor for Go
Stale — last commit 2y ago
weakest axisnon-standard license (Other); last commit was 2y ago
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓27+ active contributors
- ✓Distributed ownership (top contributor 49% of recent commits)
- ✓Other licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 2y ago
- ⚠Non-standard license (Other) — review terms
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/russross/blackfriday)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/russross/blackfriday on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: russross/blackfriday
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/russross/blackfriday shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 2y ago
- 27+ active contributors
- Distributed ownership (top contributor 49% of recent commits)
- Other licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
- ⚠ Non-standard license (Other) — review terms
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live russross/blackfriday
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/russross/blackfriday.
What it runs against: a local clone of russross/blackfriday — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in russross/blackfriday | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 860 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of russross/blackfriday. If you don't
# have one yet, run these first:
#
# git clone https://github.com/russross/blackfriday.git
# cd blackfriday
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of russross/blackfriday and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "russross/blackfriday(\\.git)?\\b" \\
&& ok "origin remote is russross/blackfriday" \\
|| miss "origin remote is not russross/blackfriday (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 860 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~830d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/russross/blackfriday"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Blackfriday is a Markdown processor written in Go that converts Markdown text to HTML output. It is a high-performance, security-focused parser (paranoid about untrusted input) that supports common Markdown extensions like tables, smart punctuation substitutions (via Smartypants), and produces safe UTF-8/Unicode output. Originally a port of the C-based Sundown parser, it provides both v1 (legacy, single-call API) and v2 (modern, with separate Parse/Render steps) implementations. Single-package architecture in the repository root: block.go handles block-level parsing (paragraphs, lists, blockquotes), inline.go handles inline elements (emphasis, links, code spans), markdown.go coordinates the Parse→Render pipeline, and html.go/latex.go/smartypants.go provide renderers. testdata/ contains comprehensive CommonMark compliance test fixtures (.text input files paired with expected .html output). No internal packages or complex module hierarchy.
👥Who it's for
Go backend developers and CLI tool authors who need to render user-supplied or document Markdown safely without external dependencies; teams building documentation systems, static site generators, or content platforms that require embedded Markdown parsing with security guarantees.
🌱Maturity & risk
Production-ready and actively maintained. The v2 branch is the current recommendation with comprehensive test coverage (block_test.go, inline_test.go, markdown_test.go, ref_test.go) and CI/CD via Travis CI (.travis.yml). v1 is in legacy mode but still available at github.com/russross/blackfriday with security updates. The project is stable but not under heavy active development—v2 was established as the recommended version and remains the focus.
Low risk for production use. Single-maintainer project (russross), so feature velocity depends on one person, but the codebase is mature and well-tested with no recent breaking changes visible. Known limitation: v2 is ~15% slower than v1 per benchmarks, and some bug fixes are trailing behind v1 (tracked in issue #348). Minimal external dependencies—Go standard library focused. Go 1.13+ compatibility requirement is clear and non-aggressive.
Active areas of work
The v2 branch is the active development line; v1 (main branch) receives only security patches. No specific visible PRs or recent milestone activity in the provided snapshot, suggesting the project is in maintenance mode rather than feature development. Focus is on stability and bug fixes rather than new capabilities.
🚀Get running
Clone and test: git clone https://github.com/russross/blackfriday.git && cd blackfriday && go mod download && go test ./.... For v2: go get github.com/russross/blackfriday/v2. For basic usage: create a Go file with blackfriday.Run(input) and go run it.
Daily commands:
Development: go test ./... runs the test suite. No dev server (it's a library, not a service). To process Markdown in a Go program: import "github.com/russross/blackfriday/v2" then html := blackfriday.Run(markdownInput). No CLI tool provided in the main distribution.
🗺️Map of the codebase
- markdown.go: Core parser orchestration: defines Markdown struct, Parse() method that builds AST, and Render() that walks the tree—the entry point for understanding the v2 two-phase architecture
- block.go: Block-level element parsing: recognizes paragraphs, lists, blockquotes, code blocks, headings—the foundation of Markdown document structure
- inline.go: Inline element parsing: handles emphasis, links, code spans, strikethrough—runs after block parsing to parse content within block elements
- html.go: Default HTML renderer: implements Renderer interface to convert AST nodes to HTML output; shows the pattern for custom renderers
- testdata/: CommonMark compliance test suite: .text files are Markdown inputs, paired .html files are expected outputs; ensures parser handles edge cases correctly
- smartypants.go: Typography enhancement processor: post-processes HTML output to convert quotes, dashes, ellipses to smart variants; optional extension
- markdown_test.go: End-to-end integration tests: validates complete Parse→Render pipeline against testdata fixtures; key for regression detection
🛠️How to make changes
Start with block.go or inline.go depending on whether you're adding block-level (heading, list) or inline-level (bold, link) syntax. Add test cases to testdata/ as .text and .html file pairs, then run go test to verify. For new Markdown extension parsing: hook into the Parse phase in markdown.go. For custom output: implement the Renderer interface (see html.go as reference). Always add tests in *_test.go files using the testdata fixtures.
🪤Traps & gotchas
No environment variables required; no external services. Trap: Go 1.13+ is a hard requirement (check go.mod), older Go versions will not work. Trap: The v1 (legacy) and v2 APIs are incompatible—mixing imports from github.com/russross/blackfriday and github.com/russross/blackfriday/v2 in the same codebase will cause conflicts. Trap: Performance differs ~15% between v1 and v2; if benchmarking matters, measure both. No Trap: testdata test discovery is not automatic—tests manually load files, so adding testdata pairs requires no special build configuration.
💡Concepts to learn
- Recursive descent parsing — Blackfriday's parser (markdown.go, block.go, inline.go) uses recursive descent to handle nested structures like nested lists and blockquotes; understanding this pattern is essential to modify the parser without breaking nesting behavior
- Abstract Syntax Tree (AST) — Blackfriday v2's separation of Parse (builds AST) and Render (walks AST) is the core architectural innovation; understanding how Node objects are built and traversed is key to custom renderers and extensions
- Visitor pattern (Renderer interface) — The Renderer interface allows pluggable output formats (HTMLRenderer, LaTeXRenderer); new contributors need to understand how to walk the AST and emit output without modifying the parser
- Lexical analysis / tokenization — Block.go and inline.go perform character-level scanning and token recognition (e.g., identifying list markers, emphasis delimiters); understanding rune iteration and byte boundaries is crucial for fixing parsing bugs
- Security: input sanitization vs. output escaping — Blackfriday claims to be 'paranoid' about untrusted input; understanding the difference between safe parsing (rejecting malformed input) and safe output (escaping HTML/LaTeX special chars in html.go) is critical for maintaining security guarantees
- CommonMark specification compliance — The testdata/ directory enforces CommonMark compliance; understanding the spec (ambiguous precedence, edge cases for emphasis, list item nesting rules) explains why specific test cases exist and what changes are safe
- UTF-8 / Unicode handling in Go — The README emphasizes 'safe for all utf-8 (unicode) input'; Go's rune type and string iteration behavior differs from byte slices—critical for inline parsing (inline.go) when handling non-ASCII characters in emphasis/links
🔗Related repos
commonmark/commonmark-spec— Official CommonMark specification repository; defines the Markdown standard that Blackfriday aims to implement, essential for understanding parsing correctnessgomarkdown/markdown— Alternative pure-Go Markdown parser with similar goals; useful for comparing architectural decisions and feature parity in the Go ecosystemmarkdownit/markdown-it— Popular Node.js Markdown parser with plugin architecture; Blackfriday v2's design (Parse→Render separation) mirrors this two-phase approach for extensibilityjgm/pandoc— Universal document converter written in Haskell; Blackfriday extends this concept by supporting multiple output formats (HTML, LaTeX) from the same Markdown input via Renderer interface
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for LaTeX output rendering
The repo has latex.go for LaTeX output support, but there are no corresponding latex_test.go tests or LaTeX testdata files. While HTML has extensive testdata (Amps and angle encoding, Code blocks, etc.), LaTeX rendering is untested. This is critical for ensuring LaTeX output quality and preventing regressions.
- [ ] Create latex_test.go with test cases mirroring the structure of html_test.go and inline_test.go
- [ ] Add LaTeX testdata files (e.g., testdata/*.latex files) covering: code blocks, math expressions, special character escaping, lists, and blockquotes
- [ ] Ensure tests validate LaTeX-specific concerns like proper escaping of backslashes and special symbols
- [ ] Run tests against existing markdown testdata to establish baseline LaTeX output coverage
Migrate from Travis CI to GitHub Actions for modern CI/CD
The repo uses .travis.yml (outdated Travis CI config). GitHub Actions is the modern standard for GitHub-hosted projects, offers better integration, free minutes, and improved visibility. The go.mod specifies Go 1.13 (released 2019), so testing against modern Go versions (1.20+) would catch compatibility issues.
- [ ] Create .github/workflows/test.yml with matrix testing across Go 1.13, 1.19, 1.20, and latest
- [ ] Include steps for: go test ./..., go vet ./..., and gofmt verification
- [ ] Add workflow to run on push and pull_request events
- [ ] Document the new CI setup in README.md or CONTRIBUTING.md
- [ ] Remove or archive .travis.yml
Add integration tests for Smartypants extension with testdata
The repo has smartypants.go but smartypants functionality lacks dedicated test coverage and testdata examples. Smartypants performs subtle transformations (quotes, dashes, ellipses), which are easy to regress. Adding testdata files (similar to existing .text/.html pairs) would ensure these transformations work correctly across edge cases.
- [ ] Create testdata files for smartypants: 'Smartypants quotes.text', 'Smartypants quotes.html', 'Smartypants dashes.text', 'Smartypants dashes.html', etc.
- [ ] Add test cases in markdown_test.go or a new smartypants_test.go that explicitly enable the Smartypants flag
- [ ] Cover edge cases: nested quotes, em-dashes vs en-dashes, ellipsis spacing, apostrophes in contractions
- [ ] Validate output matches expected transformations per Smartypants spec
🌿Good first issues
- Add parser support for GitHub-style task lists (
- [ ] itemsyntax) by extending block.go and inline.go to recognize task list markers, then add test cases to testdata/ with .text and .html fixtures for checkbox lists. - Improve HTML sanitization documentation and add examples in README.md for safe rendering of user-supplied Markdown—currently the README mentions paranoid input handling but lacks concrete examples of how untrusted data flows through Parse/Render safely.
- Expand LaTeX renderer coverage: latex.go currently supports basic elements; add support for additional block types (tables, footnotes) by studying existing html.go patterns and adding test fixtures to testdata/ for LaTeX output validation.
⭐Top contributors
Click to expand
Top contributors
📝Recent commits
Click to expand
Recent commits
e96880f— README: make a definitive decision on v2 import path (dmitshur)abb995c— Merge pull request #586 from kolyshkin/gomod (russross)665c4de— go.mod: add go version (kolyshkin)41c5fcc— Merge pull request #559 from alanhdu/patch-1 (russross)75d2440— Merge pull request #570 from orf/add-no-opener (russross)89e6d96— Merge pull request #580 from MarkAtwood/master (russross)c04ab11— Update LICENSE.txt (MarkAtwood)41eb1fe— Backport noopener links (from commit 670777b536d38a1aef1d517f6330a77d52ceb02e) (orf)e2f6cd9— Add <summary> tag too (Alan Du)5c6bc5d— Add <details> to recognized HTML5 block tags (Alan Du)
🔒Security observations
Blackfriday is a markdown processor with a reasonable security foundation but has several areas requiring attention. The primary concerns are: (1) the outdated Go version (1.13) which may contain unpatched vulnerabilities, (2) potential XSS risks in HTML output generation that require verification, and (3) insufficient security documentation and disclosure policies. The codebase appears to have minimal external dependencies which is positive for supply chain security. However, the lack of explicit security validation documentation despite claims of being 'paranoid about input' is concerning. The project would benefit from modernizing its Go version, adding comprehensive security tests, documenting input validation logic, and establishing a security vulnerability disclosure process.
- High · Potential XSS Vulnerability in HTML Output —
html.go, inline.go, block.go. Blackfriday processes markdown and outputs HTML. The codebase contains html.go which generates HTML output. If user-supplied markdown is not properly sanitized before HTML generation, it could lead to XSS attacks. While the README claims the tool is 'paranoid about its input', the actual HTML escaping implementation needs verification to ensure all dangerous HTML tags and JavaScript contexts are properly escaped. Fix: Verify that all HTML special characters are properly escaped using encoding/html package. Ensure that user-controlled content cannot break out of HTML context. Consider implementing a whitelist of allowed HTML tags if raw HTML pass-through is supported. Add security-focused unit tests for XSS payloads. - Medium · Outdated Go Version Dependency —
go.mod. The go.mod file specifies 'go 1.13' which was released in September 2019 and is significantly outdated. Go 1.13 has reached end-of-life and likely contains unpatched security vulnerabilities. Dependencies compiled against old Go versions may have known security issues. Fix: Update the minimum Go version to at least 1.19 or the latest stable release. Run 'go get -u' to update dependencies and test thoroughly. Consider using Go 1.21+ for improved security patches. - Medium · No SBOM or Dependency Audit Visible —
go.mod, .travis.yml. The repository has minimal dependencies listed (go.mod shows no external dependencies), but there is no evidence of dependency scanning, vulnerability audits, or Software Bill of Materials (SBOM). Without regular dependency audits, supply chain vulnerabilities could be missed. Fix: Implement 'go mod tidy' and 'go mod audit' in CI/CD pipeline. Consider using GitHub Dependabot or Snyk for continuous vulnerability scanning. Generate and maintain an SBOM for the project. - Medium · Incomplete Input Validation Documentation —
README.md, block.go, inline.go. While the README claims the tool is 'paranoid about its input', there is no detailed documentation or comments in the code explaining what validation is performed, what is considered unsafe, or what edge cases are handled. This makes it difficult for users to understand the actual security guarantees. Fix: Add comprehensive security documentation explaining: (1) What input validation is performed, (2) Known limitations or bypass techniques, (3) Recommended use cases, (4) Examples of safe and unsafe usage patterns. Add inline code comments for security-critical sections. - Low · Missing Security Headers in CI Configuration —
.travis.yml. The .travis.yml file is present but not shown in detail. Travis CI configurations often lack security best practices such as encrypted environment variables, branch protection rules, or signed commits. Fix: Review and configure: (1) Use encrypted secrets for any credentials, (2) Enable branch protection rules, (3) Require code review for merges, (4) Use signed commits, (5) Enable security scanning in the CI/CD pipeline. - Low · No Security Policy or Vulnerability Disclosure Process —
Repository root. No SECURITY.md file or security policy is visible in the repository. This makes it unclear how to report security vulnerabilities responsibly. Fix: Create a SECURITY.md file that includes: (1) Instructions for responsible vulnerability disclosure, (2) Security contact information, (3) Expected response timeframe, (4) Acknowledgment process for security researchers.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.