remark

package module
v0.0.0-...-cdde61f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2025 License: MIT Imports: 8 Imported by: 0

README

🎯 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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Appendable

type Appendable interface {
	Tag
	Append(tag Tag)
}

type Attributable

type Attributable interface {
	Attrs() Attributes
}

type Attributes

type Attributes map[string]string

func (Attributes) Add

func (at Attributes) Add(key string, value string)

func (Attributes) Attrs

func (at Attributes) Attrs() Attributes

func (Attributes) Get

func (at Attributes) Get(key string) (string, bool)

func (Attributes) Options

func (at Attributes) Options() tags.Options

func (Attributes) Set

func (at Attributes) Set(key string, value string)

func (Attributes) String

func (a Attributes) String() string

type Code

type Code struct {
	*Generic
}

func (*Code) HTML

func (code *Code) HTML() template.HTML

func (Code) Name

func (code Code) Name() string

func (Code) String

func (code Code) String() string

type CodeBlock

type CodeBlock struct {
	*Generic
	Language string
	Snippets Snippets
}

func (*CodeBlock) HTML

func (code *CodeBlock) HTML() template.HTML

func (CodeBlock) ID

func (code CodeBlock) ID() string

func (CodeBlock) Name

func (code CodeBlock) Name() string

func (CodeBlock) String

func (code CodeBlock) String() string

type Generic

type Generic struct {
	Attributes
	Children Tags
	Name     string
	Data     Metadata
}

func NewGeneric

func NewGeneric(name string) *Generic

func (*Generic) Append

func (t *Generic) Append(tag Tag)

func (*Generic) GetChildren

func (t *Generic) GetChildren() Tags

func (*Generic) Metadata

func (t *Generic) Metadata() Metadata

func (Generic) String

func (tag Generic) String() string

func (*Generic) TagName

func (t *Generic) TagName() string

type Heading

type Heading struct {
	*Generic
	Level int
}

type Image

type Image struct {
	*Generic
}

type Include

type Include struct {
	*Generic
}

func (Include) String

func (i Include) String() string

type Metadata

type Metadata map[string]string

func (Metadata) Attrs

func (md Metadata) Attrs() Attributes

func (Metadata) GetChildren

func (md Metadata) GetChildren() Tags

func (Metadata) HTML

func (md Metadata) HTML() template.HTML

func (Metadata) Options

func (md Metadata) Options() tags.Options

func (Metadata) String

func (md Metadata) String() string

func (Metadata) TagName

func (md Metadata) TagName() string

type Metadatable

type Metadatable interface {
	Tag
	Metadata() Metadata
}

type Overviewable

type Overviewable interface {
	Tag
	Overview() bool
}

type Snippet

type Snippet struct {
	Content  string
	File     string
	Language string
	Name     string
	Start    int
	End      int
}

func (Snippet) HTML

func (snip Snippet) HTML() template.HTML

type Snippets

type Snippets map[string]Snippet

type String

type String string

func (String) Attrs

func (s String) Attrs() Attributes

func (String) GetChildren

func (s String) GetChildren() Tags

func (String) Options

func (s String) Options() tags.Options

func (String) String

func (s String) String() string

func (String) TagName

func (s String) TagName() string

type Summaryable

type Summaryable interface {
	Tag
	Summary() bool
}

type Tag

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

func Noop

func Noop() Tag

type Tags

type Tags []Tag

func (Tags) Body

func (tags Tags) Body() (Tag, bool)

func (Tags) FindAll

func (tags Tags) FindAll(name string) Tags

func (Tags) FindFirst

func (tags Tags) FindFirst(name string) (Tag, bool)

func (Tags) Overview

func (tags Tags) Overview() string

func (Tags) String

func (tags Tags) String() string

Directories

Path Synopsis
cmd
remark command
retoc command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL