sectionwrapper

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2025 License: MIT Imports: 7 Imported by: 0

README

Goldmark Section Wrapper Extension

GitHub go.mod Go version GitHub License GitHub commit activity GitHub Tag

This is a Goldmark extension that automatically wraps headings and their content in HTML <section> elements with proper nesting. This extension transforms your Markdown document structure into semantic HTML sections, making it easier to style and navigate.

Installation

go get github.com/zmtcreative/gm-sectionwrapper

Basic Usage

package main

import (
    "bytes"
    "fmt"

    "github.com/yuin/goldmark"
    sectionwrapper "github.com/zmtcreative/gm-sectionwrapper"
)

func main() {
    md := goldmark.New(
        goldmark.WithExtensions(
            sectionwrapper.NewSectionWrapper(),
        ),
    )

    source := `# Main Section
This is some content.

## Subsection
More content here.`

    var buf bytes.Buffer
    if err := md.Convert([]byte(source), &buf); err != nil {
        panic(err)
    }
    fmt.Print(buf.String())
}

Output:

<section class="section-h1"><h1>Main Section</h1>
<p>This is some content.</p>
<section class="section-h2"><h2>Subsection</h2>
<p>More content here.</p>
</section></section>
Alternative Initialization Method

If you just want the default behavior without any options (i.e., just use the section-h? class in the HTML output) you can also initialize the extension using the following method:

    md := goldmark.New(
        goldmark.WithExtensions(sectionwrapper.SectionWrapper),
    )

Configuration Options

The extension provides several configuration options through functional options:

WithSectionClass(enabled bool)

Controls whether to add section-h{level} classes to section elements.

  • Default: true
  • Example: section-h1, section-h2, etc.
// Disable section-h{level} classes
md := goldmark.New(
    goldmark.WithExtensions(
        sectionwrapper.NewSectionWrapper(
            sectionwrapper.WithSectionClass(false),
        ),
    ),
)
WithHeadingClass(enabled bool)

Controls whether to add h{level} classes to section elements.

  • Default: false
  • Example Class Entry: h1, h2, etc.
// Enable heading-level classes
md := goldmark.New(
    goldmark.WithExtensions(
        sectionwrapper.NewSectionWrapper(
            sectionwrapper.WithHeadingClass(true),
        ),
    ),
)
WithCustomClassPrefix(prefix string)

Adds a custom prefix followed by the heading level to section elements.

  • Default: "" (empty)
  • Example Class Entry: With prefix "custom-" => custom-h1, custom-h2, etc.
// Add custom prefix
md := goldmark.New(
    goldmark.WithExtensions(
        sectionwrapper.NewSectionWrapper(
            sectionwrapper.WithCustomClassPrefix("my-"),
        ),
    ),
)
WithCustomClass(class string)

Adds a fixed custom class to all section elements regardless of heading level.

  • Default: "" (empty)
  • Example Class Entry: "content-section"
// Add custom class to all sections
md := goldmark.New(
    goldmark.WithExtensions(
        sectionwrapper.NewSectionWrapper(
            sectionwrapper.WithCustomClass("content-section"),
        ),
    ),
)
Combining Options

You can combine multiple options:

md := goldmark.New(
    goldmark.WithExtensions(
        sectionwrapper.NewSectionWrapper(
            sectionwrapper.WithSectionClass(true),
            sectionwrapper.WithHeadingClass(true),
            sectionwrapper.WithCustomClassPrefix("article-"),
            sectionwrapper.WithCustomClass("content"),
        ),
    ),
)

This would produce sections with classes like: "section-h1 h1 article-h1 content"

Behavior

Nesting

Sections are properly nested based on heading hierarchy:

# Level 1
Content for level 1
## Level 2
Content for level 2
### Level 3
Content for level 3
## Another Level 2
More content

Produces properly nested <section> elements where Level 3 is inside Level 2, which is inside Level 1.

Content Handling
  • All content between headings is included in the appropriate section
  • Content before the first heading remains outside any section
  • Empty headings create empty sections
  • Supports all Markdown content types (paragraphs, lists, code blocks, blockquotes, etc.)
Heading Levels
  • Supports all heading levels (H1 through H6)
  • Handles skipped heading levels gracefully
  • Maintains proper nesting regardless of heading level jumps

Examples

Default Configuration
# Main Title
Introduction text.
## Section One
Section content.
<section class="section-h1"><h1>Main Title</h1>
<p>Introduction text.</p>
<section class="section-h2"><h2>Section One</h2>
<p>Section content.</p>
</section></section>
With All Options Enabled
sectionwrapper.NewSectionWrapper(
    sectionwrapper.WithSectionClass(true),
    sectionwrapper.WithHeadingClass(true),
    sectionwrapper.WithCustomClassPrefix("doc-"),
    sectionwrapper.WithCustomClass("section"),
)
<section class="section-h1 h1 doc-h1 section"><h1>Main Title</h1>
<p>Introduction text.</p>
<section class="section-h2 h2 doc-h2 section"><h2>Section One</h2>
<p>Section content.</p>
</section></section>

Compatibility Warning

Unit tests have been created with this extension, and it currently passes all the tests. This includes tests with the built-in Goldmark extensions (extension.GFM, extension.DefinitionList, and extension.Footnote). However, this does not guarantee the extension will work with any other extensions.

[!Important]

This extension transforms the AST structure by wrapping headings in section nodes, which could potentially conflict with other extensions that also modify heading behavior or document structure.

If you encounter issues when using this extension alongside others, please test with the extensions individually to identify conflicts.

License

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

Documentation

Index

Constants

This section is empty.

Variables

View Source
var KindSection = ast.NewNodeKind("Section")

KindSection is the node kind for SectionNode

View Source
var SectionWrapper = NewSectionWrapper()

SectionWrapper is the default instance of sectionWrapper with default settings

Functions

func NewSectionWrapper

func NewSectionWrapper(options ...SectionWrapperOption) *sectionWrapper

New creates a new sectionWrapper extension with default values and optional configurations

Types

type SectionNode

type SectionNode struct {
	ast.BaseBlock
	Level int
}

SectionNode represents a <section> element in the AST

func NewSectionNode

func NewSectionNode(level int) *SectionNode

NewSectionNode creates a new SectionNode

func (*SectionNode) Dump

func (n *SectionNode) Dump(source []byte, level int)

Dump dumps the SectionNode for debugging

func (*SectionNode) Kind

func (n *SectionNode) Kind() ast.NodeKind

Kind returns the node kind for SectionNode

type SectionWrapperOption

type SectionWrapperOption func(*sectionWrapper)

SectionWrapperOption is a function type for configuring sectionWrapper

func WithCustomClass

func WithCustomClass(class string) SectionWrapperOption

WithCustomClass sets a custom class applied to all sections

func WithCustomClassPrefix

func WithCustomClassPrefix(prefix string) SectionWrapperOption

WithCustomClassPrefix sets a custom class prefix followed by heading level

func WithHeadingClass

func WithHeadingClass(enabled bool) SectionWrapperOption

WithHeadingClass enables h{level} classes

func WithSectionClass

func WithSectionClass(enabled bool) SectionWrapperOption

WithSectionClass enables section-h{level} classes

Jump to

Keyboard shortcuts

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