Documentation
¶
Overview ¶
Package parser reads markdown files with YAML frontmatter and converts them to Post objects for the GoBlog system.
The parser uses goldmark for markdown processing and supports:
- YAML frontmatter for post metadata
- Syntax highlighting for code blocks
- Footnotes
- Auto-generated heading IDs
- HTML sanitization
Basic usage:
import (
"os"
"github.com/harrydayexe/GoBlog/pkg/parser"
)
// Parse a single file
p := parser.New()
post, err := p.ParseFile(os.DirFS("/path/to/posts"), "my-post.md")
if err != nil {
// handle error
}
// Parse all markdown files in a directory
posts, err := p.ParseDirectory(os.DirFS("/path/to/posts"))
if err != nil {
// handle error - may be ParseErrors with partial results
}
Configuration ¶
The parser can be customized using functional options:
// Disable code highlighting
p := parser.New(parser.WithCodeHighlighting(false))
// Change syntax highlighting style
p := parser.New(parser.WithCodeHighlightingStyle("dracula"))
// Enable footnote support
p := parser.New(parser.WithFootnote())
// Combine multiple options
p := parser.New(
parser.WithCodeHighlightingStyle("monokai"),
parser.WithFootnote(),
)
See the Option functions for all available configuration options.
A Parser is safe for concurrent use by multiple goroutines after creation.
Example ¶
p := New()
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "valid-post.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(post.Title)
Output: A Valid Blog Post
Example (WithOptions) ¶
// Configure parser with custom options
p := New(
WithCodeHighlightingStyle("dracula"),
WithFootnote(),
)
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "with-code.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Configured parser")
fmt.Println("Has content:", len(post.Content) > 0)
Output: Configured parser Has content: true
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type FileError ¶
type FileError struct {
Path string // Path to the file that caused the error
Err error // The underlying error
}
FileError represents an error that occurred while parsing a specific file.
type Option ¶
Option is a function which can update the parser config
func WithCodeHighlighting ¶
WithCodeHighlighting enables the highlighting of ringfenced code blocks
Note that currently Chroma is used under-the-hood, so you should refer to the styles in their documentation and source code
Example ¶
// Disable code highlighting
p := New(WithCodeHighlighting(false))
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "with-code.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Highlighting disabled")
fmt.Println("Post parsed:", post.Title != "")
Output: Highlighting disabled Post parsed: true
func WithCodeHighlightingStyle ¶
WithCodeHighlightingStyle sets the code highlighting style for ringfenced code blocks and enables code highlighting if it wasn't already
Note that currently Chroma is used under-the-hood, so you should refer to the styles in their documentation and source code
Example ¶
// Use a different syntax highlighting style
p := New(WithCodeHighlightingStyle("dracula"))
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "with-code.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Custom highlighting style")
fmt.Println("Post parsed:", post.Title != "")
Output: Custom highlighting style Post parsed: true
func WithFootnote ¶
func WithFootnote() Option
WithFootnote enables the use of PHP Markdown Extra Footnotes.
Footnotes allow you to add references and notes without cluttering the main text. Use [^1] in your text and define footnotes with [^1]: Your footnote text.
See the PHP Markdown Extra documentation for syntax details: https://michelf.ca/projects/php-markdown/extra/#footnotes
Example ¶
// Enable PHP Markdown Extra footnotes
p := New(WithFootnote())
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "with-footnotes.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Footnotes enabled")
fmt.Println("Post parsed:", post.Title != "")
Output: Footnotes enabled Post parsed: true
type ParseErrors ¶
type ParseErrors struct {
Errors []FileError
}
ParseErrors aggregates multiple parsing errors encountered during directory-wide parsing operations.
ParseErrors is returned when one or more files fail to parse, but other files may have been successfully parsed. Check the Errors slice to see all individual failures.
func (ParseErrors) Error ¶
func (pe ParseErrors) Error() string
Error implements the error interface, returning a formatted multi-line error message listing all file errors.
func (ParseErrors) HasErrors ¶
func (pe ParseErrors) HasErrors() bool
HasErrors returns true if there are any errors in the collection.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser reads markdown files and converts them to Post objects. A Parser is safe for concurrent use after creation.
func New ¶
New creates a new Parser with the specified options. The parser is configured with: - YAML frontmatter parsing - Syntax highlighting for code blocks (enabled by default, use WithCodeHighlighting to disable) - Optional footnote support (disabled by default, use WithFootnote to enable) - Auto-generated heading IDs - HTML sanitization (unsafe HTML disabled by default)
func (*Parser) ParseDirectory ¶
ParseDirectory walks the filesystem and parses all .md files found. It returns a PostList containing all successfully parsed posts, sorted by date (newest first).
If any files fail to parse, ParseDirectory continues processing remaining files and returns both the valid posts and a ParseErrors containing all failures. Callers can check the error and decide whether to proceed with partial results or fail entirely.
Only files with .md or .markdown extensions are processed. Other files and directories are silently skipped.
Example ¶
p := New(WithFootnote())
fsys := os.DirFS("testdata")
posts, err := p.ParseDirectory(fsys)
// Partial results may be returned with errors
if err != nil {
if parseErrs, ok := err.(ParseErrors); ok {
fmt.Printf("Parsed with some errors\n")
fmt.Printf("Valid posts: %d\n", len(posts))
fmt.Printf("Errors: %d\n", len(parseErrs.Errors))
return
}
}
fmt.Printf("Valid posts: %d\n", len(posts))
Output: Parsed with some errors Valid posts: 3 Errors: 4
func (*Parser) ParseFile ¶
ParseFile reads and parses a single markdown file from the filesystem. It extracts frontmatter metadata, validates required fields, renders the markdown content to HTML, and returns a fully populated Post.
The file must contain YAML frontmatter with at minimum: title, date, and description. The markdown body is rendered to HTML with syntax highlighting and footnote support.
Returns an error if the file cannot be read, frontmatter is invalid, required fields are missing, or markdown rendering fails.
Example ¶
p := New()
fsys := os.DirFS("testdata")
post, err := p.ParseFile(fsys, "valid-post.md")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Title: %s\n", post.Title)
fmt.Printf("Tags: %d\n", len(post.Tags))
Output: Title: A Valid Blog Post Tags: 3