A fast, extensible, and well-structured markdown parser for Go, optimized for simplicity and performance.
- π Fast & Lightweight: Simple token-based parsing with excellent performance
- π§© Extensible: Modular architecture with configurable extensions
- π Standards Compliant: Supports CommonMark with useful extensions
- π Roundtrip Support: Parse β modify β restore back to markdown
- π‘οΈ Type Safe: Clean Go interfaces with comprehensive error handling
- π§ͺ Well Tested: Comprehensive test suite with high coverage
- Text formatting: Bold, italic, bold-italic, strikethrough
- Code: Inline code and fenced code blocks
- Links & Images: Manual links, auto-links, and images
- Lists: Ordered, unordered, and task lists
- Structure: Headings, paragraphs, blockquotes, horizontal rules
- Tables: GitHub-flavored table syntax
- Math: Inline (
$math$
) and block ($$math$$
) expressions - Highlighting:
==highlighted text==
- Subscript/Superscript:
~sub~
and^super^
- Spoilers:
||spoiler text||
- Tags:
#hashtag
syntax - Referenced Content:
[[wiki-style]]
links - Embedded Content:
![[embeds]]
- HTML Elements:
<kbd>
,<br>
,<img>
,<small>
,<mark>
, and more
gomark is designed for zero-configuration usage - all features are enabled by default:
package main
import (
"fmt"
"github.com/usememos/gomark"
"github.com/usememos/gomark/renderer/html"
)
func main() {
// All features enabled by default - no configuration needed!
markdown := `# Hello Memos!
**Bold** and *italic* text with ==highlighting==.
Press <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy.
Math: $E = mc^2$ and task lists:
- [x] HTML elements supported
- [ ] Even more features coming
#gomark ||works great||!`
// Parse with all features enabled
doc, err := gomark.Parse(markdown)
if err != nil {
panic(err)
}
// Render to HTML
renderer := html.NewHTMLRenderer()
html := renderer.RenderDocument(doc)
fmt.Println(html)
// Or restore back to markdown
restored := gomark.Restore(doc)
fmt.Println(restored)
}
While gomark works great with zero configuration, you can customize it if needed:
import (
"github.com/usememos/gomark"
"github.com/usememos/gomark/config"
)
// Customize limits if needed
engine := gomark.NewEngine(gomark.WithConfig(
config.DefaultConfig().WithMaxDepth(100).WithMaxFileSize(1024 * 1024), // 1MB limit
))
doc, err := engine.Parse(markdown)
import (
"github.com/usememos/gomark/renderer"
"github.com/usememos/gomark/renderer/html"
"github.com/usememos/gomark/renderer/string"
)
// Parse once, render to multiple formats
doc, _ := gomark.Parse(markdown)
// Render to HTML
htmlRenderer := html.NewHTMLRenderer()
htmlOutput := htmlRenderer.RenderDocument(doc)
// Extract plain text
stringRenderer := string.NewStringRenderer()
textOutput := stringRenderer.RenderDocument(doc)
// Render back to markdown (roundtrip)
markdownOutput := gomark.Restore(doc)
import "github.com/usememos/gomark/config"
// Default configuration: all features enabled with generous limits
cfg := config.DefaultConfig()
// Custom limits if needed
cfg := config.DefaultConfig().
WithMaxDepth(50). // Limit nesting depth
WithMaxFileSize(1024 * 1024) // 1MB file size limit
gomark follows a clean, modular architecture:
gomark/
βββ ast/ # Abstract Syntax Tree definitions
βββ config/ # Configuration management
βββ parser/ # Parsing logic and tokenization
β βββ internal/ # Parser implementations
β βββ tokenizer/ # Tokenization engine
β βββ tests/ # Comprehensive parser tests
βββ renderer/ # Output rendering
β βββ html/ # HTML renderer
β βββ markdown/ # Markdown renderer (roundtrip)
β βββ string/ # Plain text renderer
βββ gomark.go # Main engine and public API
- Simplicity over Complexity: Clean, understandable code
- Performance over Features: Fast parsing with minimal overhead
- Extensibility: Easy to add new features without breaking existing code
- Type Safety: Proper Go interfaces and error handling
- Testing: Comprehensive test coverage for reliability
gomark is designed for performance:
- Token-based parsing: Efficient single-pass tokenization
- Minimal allocations: Reuses buffers and objects where possible
- Simple AST: Direct field access instead of complex tree operations
- Focused scope: Implements what's needed, not theoretical features
All extensions can be configured via the config package:
cfg := config.DefaultConfig()
// Disable specific extensions
cfg = cfg.WithExtension("tables", false)
cfg = cfg.WithExtension("math", false)
// Enable strict parsing
cfg = cfg.WithStrictMode(true)
// Enable safe mode (sanitizes content)
cfg = cfg.WithSafeMode(true)
Extension | Default | Description |
---|---|---|
tables |
β | GitHub-flavored table syntax |
strikethrough |
β | ~~strikethrough~~ text |
autolinks |
β | Automatic URL detection |
tasklists |
β | - [ ] and - [x] checkboxes |
math |
β | $inline$ and $$block$$ math |
highlighting |
β | ==highlighted== text |
subscript |
β | ~subscript~ text |
superscript |
β | ^superscript^ text |
spoilers |
β | ||spoiler|| text |
embedded |
β | ![[embedded]] content |
references |
β | [[referenced]] content |
tags |
β | #hashtag syntax |
- β
Phase 1 HTML Elements: Added support for
<kbd>
,<br>
,<img>
,<small>
,<mark>
- β Simplified Configuration: Zero-config usage with sensible defaults
- β Enhanced HTML Parsing: Proper attribute handling and self-closing tag support
- β Fixed blockquote blank lines (GitHub issue #19)
- β Refactored to modular architecture
- β Improved package organization with public APIs
- β Enhanced test coverage with 26+ HTML element test cases
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
go test ./...
- Submit a pull request
This project is part of the Memos ecosystem.
Designed for simplicity, performance, and ease of use. gomark focuses on practical markdown parsing with clean, maintainable code.