Skip to content

gopherguides/remark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎯 Remark - Advanced Markdown Processing & HTML Generation

⚠️ DEPRECATION NOTICE This project is no longer maintained and has been completely replaced by a ground-up rebuild in the Hype project. Please use Hype for all new projects.

Tests codecov GoDoc Go Report Card

Remark is a powerful Go package that transforms markdown into structured, processable content. Built for educational platforms, documentation systems, and content management, it provides a sophisticated tag-based architecture for parsing, processing, and rendering markdown with advanced features like file inclusion, code syntax highlighting, metadata extraction, and HTML generation.

🚀 Features

Core Capabilities

  • Dual Parser Support: Process both Markdown (md) and HTML (htm) content
  • Tag-Based Architecture: Structured content representation through a unified Tag interface
  • File Inclusion: Dynamic content composition with <include> tags
  • Advanced Code Blocks: Syntax highlighting with snippet support and language detection
  • Metadata Extraction: Parse and process document metadata from HTML details tags
  • Section Management: Automatic content sectioning with horizontal rule delimiters
  • HTML Generation: Convert processed content to clean HTML output
  • Table of Contents: Generate structured TOCs from heading hierarchies

Advanced Features

  • Template Processing: Go template integration for dynamic content generation
  • Image Processing: Automatic image validation and path resolution
  • Link Processing: Smart link handling and validation
  • Attribute Management: Rich attribute system for all content elements
  • Custom Printers: Extensible rendering system with custom tag processors
  • Snippet Management: Advanced code snippet extraction and processing

📦 Installation

Package Installation

go get github.com/gopherguides/remark

CLI Tools

# Install the remark CLI processor
go install github.com/gopherguides/remark/cmd/remark@latest

# Install the table of contents generator
go install github.com/gopherguides/remark/cmd/retoc@latest

🎮 Quick Start

Basic Markdown Processing

package main

import (
    "fmt"
    "github.com/gopherguides/remark/md"
)

func main() {
    markdown := `# Hello World

This is a **markdown** document with:
- Lists
- Code blocks
- And more!

## Code Example

` + "```go" + `
func main() {
    fmt.Println("Hello, World!")
}
` + "```" + `
`

    // Parse the markdown
    tags, err := md.Parse(".", []byte(markdown))
    if err != nil {
        panic(err)
    }

    // Output the processed content
    fmt.Println(tags)
}

Advanced Processing with File Inclusion

# My Course Module

Welcome to the course!

---

<include src="setup.md"></include>

---

<include src="assignments/assignment01.md"></include>

HTML Processing

package main

import (
    "fmt"
    "github.com/gopherguides/remark/htm"
)

func main() {
    html := `<div class="content">
        <h1>Course Title</h1>
        <details>
            course: advanced-go
            difficulty: intermediate
        </details>
        <code src="./examples/hello.go"></code>
    </div>`

    // Parse HTML content
    doc, err := htm.Parse([]byte(html))
    if err != nil {
        panic(err)
    }

    // Access metadata
    metadata := doc.Metadata()
    fmt.Printf("Course: %s\n", metadata["course"])
    fmt.Printf("Difficulty: %s\n", metadata["difficulty"])
}

🛠️ CLI Tools

remark - Markdown Processor

Process markdown from stdin and output structured content:

# Process a markdown file
cat document.md | remark

# Set working directory for includes
MARKED_ORIGIN=/path/to/content cat document.md | remark

retoc - Table of Contents Generator

Generate structured table of contents from markdown files:

# Generate TOC for specific files
retoc /path/to/content/

# Example output:
# Course Introduction
#     Getting Started
#     Requirements
#         System Requirements
#         Software Installation
#     First Steps

🏗️ Architecture

Tag System

Remark uses a unified Tag interface for all content elements:

type Tag interface {
    Attrs() Attributes
    GetChildren() Tags
    Options() tags.Options
    TagName() string
    fmt.Stringer
}

Core Components

1. Generic Tags

Universal container for any HTML-like element:

generic := remark.NewGeneric("div")
generic.Set("class", "content")
generic.Append(remark.String("Hello World"))

2. Headings

Structured heading elements with level information:

type Heading struct {
    *Generic
    Level int  // 1-6 for h1-h6
}

3. Code Blocks

Advanced code processing with syntax highlighting:

type CodeBlock struct {
    *Generic
    Language string
    Snippets Snippets
}

4. Sections

Document sections with metadata support:

type Section struct {
    *Generic
    Title string
}

Parsers

Markdown Parser (md)

  • Full CommonMark compliance
  • Extended syntax support (tables, strikethrough, etc.)
  • Template processing
  • File inclusion
  • Custom extension support

HTML Parser (htm)

  • Clean HTML parsing
  • Metadata extraction from <details> tags
  • Image validation
  • Custom tag processing

🎯 Use Cases

Educational Content Management

Perfect for course materials, tutorials, and documentation:

# Week 1: Introduction to Go

<details>
overview: true
difficulty: beginner
duration: 2 hours
</details>

Welcome to our Go programming course!

<include src="setup-instructions.md"></include>

## Your First Program

<code src="examples/hello.go"></code>

Documentation Systems

Build comprehensive documentation with cross-references:

# API Documentation

<include src="authentication.md"></include>

<include src="endpoints/users.md"></include>

<include src="examples/complete-example.md"></include>

Content Publishing

Create rich content with embedded examples:

# Tutorial: Building a Web Server

<code src="server.go" snippet="basic-server"></code>

The code above shows...

<code src="server.go" snippet="with-middleware"></code>

🔧 Advanced Features

Custom Printers

Create custom rendering logic:

printer := &htm.Printer{}

// Custom code block renderer
printer.Set("code", func(t remark.Tag) (string, error) {
    code := t.(*remark.CodeBlock)
    return fmt.Sprintf(`<pre class="custom"><code>%s</code></pre>`, 
        html.EscapeString(code.Children.String())), nil
})

// Render with custom logic
html, err := printer.Print(tags...)

Metadata Processing

Extract and use document metadata:

// Find sections with overview metadata
for _, tag := range tags {
    if section, ok := tag.(*md.Section); ok {
        if section.Overview() {
            overview := tags.Overview() // Get overview text
            fmt.Printf("Overview: %s\n", overview)
        }
    }
}

Snippet Management

Process code snippets with markers:

// In your Go file:
// snippet:start:basic-server
func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}
// snippet:end:basic-server
<code src="server.go" snippet="basic-server"></code>

🤝 Integration with Hype

Remark is designed to work seamlessly with the Hype package for advanced content generation and templating. Together, they form a powerful content processing pipeline for educational platforms and documentation systems.

📚 API Reference

Core Functions

Markdown Processing

// Parse markdown from bytes
md.Parse(root string, src []byte) (remark.Tags, error)

// Parse markdown from file
md.ParseFile(filename string) (remark.Tags, error)

// Create new parser
md.NewParser(root string) *Parser

HTML API Functions

// Parse HTML content
htm.Parse(src []byte) (*Document, error)

// Create new HTML parser
htm.NewParser(root string) *Parser

// Print tags to HTML
htm.Print(tags ...remark.Tag) (string, error)

Tag Operations

// Find specific tags
tags.FindFirst(name string) (Tag, bool)
tags.FindAll(name string) Tags

// Get document body
tags.Body() (Tag, bool)

// Extract overview
tags.Overview() string

Interfaces

Essential Interfaces

// Core tag interface
type Tag interface {
    Attrs() Attributes
    GetChildren() Tags
    Options() tags.Options
    TagName() string
    fmt.Stringer
}

// Metadata support
type Metadatable interface {
    Tag
    Metadata() Metadata
}

// Appendable content
type Appendable interface {
    Tag
    Append(tag Tag)
}

🎨 Examples

Complete Processing Pipeline

func processContentDirectory(dir string) error {
    return filepath.Walk(dir, func(path string, info os.FileInfo, 
        err error) error {
        if filepath.Ext(path) != ".md" {
            return nil
        }

        // Parse the markdown file
        tags, err := md.ParseFile(path)
        if err != nil {
            return err
        }

        // Process each section
        for _, tag := range tags {
            if section, ok := tag.(*md.Section); ok {
                fmt.Printf("Section: %s\n", section.Title)
                
                // Extract metadata
                metadata := section.Metadata()
                if difficulty, ok := metadata["difficulty"]; ok {
                    fmt.Printf("Difficulty: %s\n", difficulty)
                }

                // Find code blocks
                codeBlocks := section.GetChildren().FindAll("code")
                fmt.Printf("Code blocks: %d\n", len(codeBlocks))
            }
        }

        return nil
    })
}

Custom Content Processor

type CourseProcessor struct {
    parser *md.Parser
}

func (cp *CourseProcessor) ProcessCourse(content []byte) (*Course, error) {
    tags, err := cp.parser.Parse(content)
    if err != nil {
        return nil, err
    }

    course := &Course{
        Modules: make([]Module, 0),
    }

    for _, tag := range tags {
        if section, ok := tag.(*md.Section); ok {
            module := Module{
                Title:   section.Title,
                Content: section.GetChildren().String(),
            }

            // Extract difficulty and duration
            metadata := section.Metadata()
            module.Difficulty = metadata["difficulty"]
            module.Duration = metadata["duration"]

            course.Modules = append(course.Modules, module)
        }
    }

    return course, nil
}

🔄 Requirements

  • Go: 1.24 or higher
  • Go Modules: Required for dependency management

📝 License

This project is licensed under the MIT License. See the LICENSE file for details.

🤝 Contributing

We welcome contributions! Please see our contributing guidelines and feel free to submit issues or pull requests.

🎯 Built For

  • Educational Platforms: Course content management and delivery
  • Documentation Systems: Technical documentation with code examples
  • Content Management: Rich content processing and publishing
  • Static Site Generation: Advanced markdown processing for websites

Remark - Transform your markdown into structured, powerful content. Built with ❤️ by the Gopher Guides team.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published

Contributors 3

  •  
  •  
  •