render

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 6, 2025 License: BSD-3-Clause Imports: 13 Imported by: 0

README

Render

A flexible Go package for rendering content in different formats with configurable options and formatting.

Golang Tests codecov Go Report Card Go Reference License

Features

  • Multiple output formats (JSON, XML, text)
  • Pretty printing and custom formatting
  • Context support with cancellation
  • Buffered rendering with post-processing
  • Content type handling

Installation

go get github.com/nanoninja/render

Quick Start

// Create renderer
renderer := render.JSON()

data := map[string]string{"message": "ping"}

// Simple render
renderer.Render(os.Stdout, data)

// Pretty printed with custom indent
renderer.Render(os.Stdout, data, render.Format(
    render.Pretty(),
    render.Indent("    "),
))

Text Rendering

// Simple text
render.Text().Render(os.Stdout, "Hello World")

// With formatting
render.Text().Render(os.Stdout, "Hello %s", render.Textf("Gopher"))

Buffered Rendering

// Create buffered JSON renderer
render.Buffer(render.JSON()).Render(os.Stdout, data)

Template Rendering

package main

import (
	"embed"
	"net/http"
	"strings"
	"text/template"

	"github.com/nanoninja/render"
	"github.com/nanoninja/render/tmpl"
	"github.com/nanoninja/render/tmpl/loader"
)

//go:embed templates
var templatesFS embed.FS

func main() {
	// Create a loader for your templates
	src := loader.NewEmbed(templatesFS, tmpl.LoaderConfig{
		Root:      "templates",
		Extension: ".html",
	})

	// Create template with configuration
	t := tmpl.HTML("",
		tmpl.SetFuncsHTML(template.FuncMap{
			"upper": strings.ToUpper,
		}),
		tmpl.LoadHTML(src),
	)

	// Use in an HTTP handler
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		data := map[string]any{"Title": "Welcome"}

		t.RenderContext(r.Context(), w, data,
			render.Name("index.html"), // Specify which template to render
			render.WriteResponse(w),   // Write headers to response
		)
	})

	http.ListenAndServe("localhost:8080", nil)
}

Context Support

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

renderer.RenderContext(ctx, w, data)

Configuration

Format Options

Options can be configured using functional options:

// Pretty printing with custom format
renderer.Render(w, data, render.Format(
    render.Pretty(),          // Enable pretty printing
    render.Indent("    "),    // Custom indentation
    render.LineEnding("\n"),  // Line ending style
    render.Prefix("// ")      // Line prefix
))

// CSV specific options
renderer.Render(w, data, render.Format(
    render.Separator(";"),    // Use semicolon as separator
    render.UseCRLF(),         // Use Windows-style line endings
))
Other Options
// Set template name (for template renderers)
renderer.Render(w, data, render.Name("index.html"))

// Set render timeout
renderer.Render(w, data, render.Timeout(5*time.Second))

// Custom parameters
renderer.Render(w, data, render.Param("key", "value"))

// Combining multiple options
renderer.Render(w, data, render.With(
    render.MimeJSON(),
    render.Format(render.Pretty()),
    render.Timeout(5*time.Second),
))
In HTTP Context
func handleJSON(w http.ResponseWriter, r *http.Request) {
    data := struct {
        Message string `json:"message"`
    }{
        Message: "Hello, World!",
    }

    renderer := render.JSON()
    renderer.Render(w, data,
        render.MimeJSON(),             // Set Content-Type
        render.WriteResponse(w),       // Write headers to response
        render.Format(render.Pretty()) // Pretty print output
    )
}

Creating Custom Renderers

You can create your own renderers to support any output format. Here's a complete guide to implementing a custom renderer.

Basic Implementation

Your renderer must implement the Renderer interface. Here's a minimal example:

type CustomRenderer struct {}

func (r *CustomRenderer) Render(w io.Writer, data any, opts func(*render.Options)) error {
    return r.RenderContext(context.Background(), w, data, opts...)
}

func (r *CustomRenderer) RenderContext(ctx context.Context, w io.Writer, data any, opts ...func(*render.Options)) error {
    // Check context validity
    if err := render.CheckContext(ctx); err != nil {
        return err
    }

    // Get options with default values
    opt := render.NewOptions(opts...)

    // Your rendering logic here
    return nil
}
Available Utilities
  • NewOptions: Processes option functions and returns configured Options
  • CheckContext: Verifies if the context is still valid Common option handlers for content type, formatting, etc.

License

This project is licensed under the BSD 3-Clause License.

It allows you to:

  • Use the software commercially
  • Modify the software
  • Distribute the software
  • Place warranty on the software
  • Use the software privately

The only requirements are:

  • Include the copyright notice
  • Include the license text
  • Not use the author's name to promote derived products without permission

For more details, see the LICENSE file in the project repository.

Documentation

Overview

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

doc.go Package render provides a flexible and extensible rendering system for Go applications.

This package is designed to handle various output formats (JSON, Text, HTML templates, etc.) in a consistent way, while maintaining type safety and providing rich configuration options.

Basic usage:

// Create a renderer
renderer := render.JSON()

// Render with options
err := renderer.Render(w, data,
    render.Format(render.Pretty()),
)

The package supports multiple renderer types:

  • Text rendering for plain text output
  • JSON rendering with support for pretty printing and JSONP
  • HTML template rendering
  • And more...

Key features:

  • Multiple output formats (JSON, XML, text)
  • Configurable formatting (indentation, pretty printing)
  • Context-aware rendering with cancellation support
  • Buffered rendering with post-processing
  • Content type handling

Each renderer implements the Renderer interface:

type Renderer interface {
    Render(w io.Writer, data any, opts ...func(*Options)) error
    RenderContext(ctx context.Context, w io.Writer, data any, opts ...func(*Options)) error
}

The package uses the options pattern for configuration, making it easy to extend and customize rendering behavior without breaking existing code.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Copyright 2025 The Nanoninja Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidContentType indicates that the content type format is invalid
	ErrInvalidContentType = errors.New("invalid content type")

	// ErrNegativeTimeout indicates that a negative duration was provided for timeout
	ErrNegativeTimeout = errors.New("timeout cannot be negative")

	// ErrInvalidParam indicates that a parameter value is invalid
	ErrInvalidParam = errors.New("invalid parameter value")

	// ErrRenderFailed indicates that the rendering process failed.
	// This can happen due to various reasons like I/O errors or formatting issues.
	ErrRenderFailed = errors.New("render failed")

	// ErrTemplateNotFound indicates that the requested template does not exist
	// in the template store or cannot be accessed.
	ErrTemplateNotFound = errors.New("template not found")

	// ErrInvalidData indicates that the provided data cannot be processed
	// by the renderer. This might happen when the data type is incompatible
	// with the chosen renderer.
	ErrInvalidData = errors.New("invalid data for renderer")
)

Package level errors that can be returned by Options validation

Functions

func Args

func Args(args ...any) func(*FormatOptions)

Args sets format arguments for text formatting operations. Example: Format(Args("Gopher"), Pretty())

func CaptureOptions

func CaptureOptions(target **Options) func(*Options)

CaptureOptions provides a way to access the options used during rendering. It returns an option function that captures the fully configured Options object.

Example:

var opts *Options
renderer.Render(w, data, CaptureOptions(&opts))
fmt.Println(opts.ContentType())

func CheckContext

func CheckContext(ctx context.Context) error

CheckContext verifies if the context is still valid. It returns nil if the context is valid, or the context error if it's done.

func Comment

func Comment(marker string) func(*FormatOptions)

Comment adds a comment marker to each line.

func Dump

func Dump(w io.Writer) func(*Options)

Dump returns an option that prints the current rendering configuration to the specified writer. This allows for flexible debugging output.

Example:

// Print options to stdout
t.Render(w, data, render.Dump(os.Stdout))

// Write options to a log file
logFile, _ := os.Create("render.log")
t.Render(w, data, render.Dump(logFile))

func Format

func Format(formatters ...func(*FormatOptions)) func(*Options)

Format applies formatting options to the render operation.

func Header(headers ...func(HeaderOptions)) func(*Options)

Header creates an option function that applies multiple header modifications. It allows configuring multiple headers in a single option using functional parameters.

func Indent

func Indent(indent string) func(*FormatOptions)

Indent sets the indentation string for formatting.

func LineEnding

func LineEnding(ending string) func(*FormatOptions)

LineEnding sets the line ending style.

func Mime

func Mime(mediatype string, charset ...string) func(*Options)

Mime returns an option function that sets the Content-Type header with an optional charset. It configures the MIME type for the rendered content, which defines how the content should be interpreted by clients. The charset parameter specifies the character encoding.

The mediatype parameter should be a valid MIME type like "text/plain" or "application/json". If a charset is provided, it's added to the Content-Type header (e.g., "text/plain; charset=utf-8").

Example:

// Set content type without charset
renderer.Render(w, data, Mime("text/plain"))

// Set content type with charset
renderer.Render(w, data, Mime("text/html", "utf-8"))

func MimeBinary

func MimeBinary() func(*Options)

MimeBinary provides default application/octet-stream content type options. Used for binary data or when the content type is unknown.

func MimeCSV

func MimeCSV() func(*Options)

MimeCSV provides default text/csv content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func MimeJSON

func MimeJSON() func(*Options)

MimeJSON provides default application/json content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func MimePDF

func MimePDF() func(*Options)

MimePDF provides default application/pdf content type options.

func MimeStream

func MimeStream() func(*Options)

MimeStream provides default application/octet-stream content type options. Used for streaming binary data.

func MimeTextHTML

func MimeTextHTML() func(*Options)

MimeTextHTML provides default text/html content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func MimeTextPlain

func MimeTextPlain() func(*Options)

MimeTextPlain provides default text/plain content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func MimeUTF8

func MimeUTF8(mediatype string) func(*Options)

MimeUTF8 returns an option function that sets the Content-Type header with UTF-8 charset. This is a convenience function that combines Mime with the UTF-8 charset, which is the most common character encoding for web content. It's equivalent to calling Mime(mediatype, "utf-8").

Example:

// Both lines are equivalent:
renderer.Render(w, data, MimeUTF8("text/plain"))
renderer.Render(w, data, Mime("text/plain", "utf-8"))

func MimeXML

func MimeXML() func(*Options)

MimeXML provides default application/xml content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func MimeYAML

func MimeYAML() func(*Options)

MimeYAML provides default application/yaml content type options with UTF-8 encoding. Can be overridden using options in Render/RenderContext methods.

func Name

func Name(name string) func(*Options)

Name sets the template name for template renderers.

func Param

func Param(key, value string) func(*Options)

Param adds a custom parameter with the given key and value. It's useful for passing additional configuration to renderers.

func Prefix

func Prefix(prefix string) func(*FormatOptions)

Prefix sets the prefix string for formatted output.

func Pretty

func Pretty() func(*FormatOptions)

Pretty enables pretty printing with default settings.

func Separator

func Separator(sep string) func(*Options)

Separator returns an option function that sets the CSV field separator. The first character of the string is used as separator. Example:

renderer.Render(w, data, Separator(";"))

func Textf

func Textf(args ...any) func(*Options)

Textf provides a convenient way to set text format arguments. It internally uses Format and Args functions to maintain consistency with the existing formatting system. Example:

txt := render.Text()
txt.Render(os.Stdout, "hello %s", render.Textf("Gopher"))

func Timeout

func Timeout(d time.Duration) func(*Options)

Timeout sets a timeout duration for the rendering operation.

func UseCRLF

func UseCRLF() func(*Options)

UseCRLF returns an option function that sets line endings to CRLF (\r\n). It combines Format and LineEnding functions to provide a convenient way to configure CRLF line endings, commonly used in CSV files for Windows compatibility and RFC 4180 compliance.

Example:

renderer.Render(w, data, UseCRLF())

This is equivalent to:

renderer.Render(w, data, Format(LineEnding("\r\n")))

func With

func With(opts ...func(*Options)) func(*Options)

With creates a reusable set of options that can be applied together. It combines multiple option functions into a single function, making it easier to manage and reuse common configuration patterns.

func WriteResponse

func WriteResponse(w http.ResponseWriter) func(*Options)

WriteResponse creates an option function that copies all headers from the Options to an http.ResponseWriter. This is useful in HTTP handlers when you need to apply the configured headers to the HTTP response.

Example:

func handleTemplate(w http.ResponseWriter, r *http.Request) {
    render.JSON().Render(w, data, render.WriteResponse(w))
}

Types

type BufferConfig

type BufferConfig struct {
	// InitialSize specifies the initial size of the buffer in bytes.
	// Setting this to a value close to the expected output size can improve
	// performance by reducing buffer reallocations.
	// If 0, the default buffer size is used.
	InitialSize int

	// PostRender defines a function to transform or validate the rendered content
	// before it is written to the output. This can be used for tasks like:
	// - Content minification
	// - Data compression
	// - Schema validation
	// - Content transformation
	// - Metadata injection
	// If nil, the content is written as-is.
	PostRender func([]byte) ([]byte, error)
}

BufferConfig holds configuration for the BufferRenderer. It allows customization of initial buffer size and post-processing functionality.

type BufferRenderer

type BufferRenderer struct {
	// contains filtered or unexported fields
}

BufferRenderer provides buffered rendering capabilities with optional post-processing. It wraps another renderer and buffers its output before writing, which allows: - Complete content validation before writing - Content transformation through post-processing - Error handling without partial writes

func Buffer

func Buffer(r Renderer) *BufferRenderer

Buffer creates a new BufferRenderer with default configuration. This is the recommended constructor for simple buffering without post-processing.

Example:

// Create a buffered JSON renderer
renderer := Buffer(JSON())
file, _ := os.Create("output.json")
renderer.Render(file, data)

func NewBuffer

func NewBuffer(r Renderer, c BufferConfig) *BufferRenderer

NewBuffer creates a BufferRenderer with custom configuration. Use this when you need to specify buffer size or add post-processing.

Example:

// Create a renderer with post-processing
renderer := NewBuffer(JSON(), BufferConfig{
    InitialSize: 4096,
    PostRender: func(data []byte) ([]byte, error) {
        // Perform content transformation
        return transform(data)
    },
})

func (*BufferRenderer) Render

func (r *BufferRenderer) Render(w io.Writer, data any, opts ...func(*Options)) error

Render implements buffered rendering using a background context. See RenderContext for details on the rendering process.

func (*BufferRenderer) RenderContext

func (r *BufferRenderer) RenderContext(ctx context.Context, w io.Writer, data any, opts ...func(*Options)) error

RenderContext implements buffered rendering with context support. The rendering process follows these steps: 1. Creates a buffer (pre-allocated if InitialSize > 0) 2. Renders content to the buffer using the wrapped renderer 3. If configured, applies post-processing to the buffered content 4. Writes the final content to the provided writer

This approach ensures that no partial content is written if an error occurs during rendering or post-processing.

type FormatOptions

type FormatOptions struct {
	// contains filtered or unexported fields
}

FormatOptions defines common formatting settings for all renderers. It provides basic text formatting capabilities that can be used across different types of output (JSON, XML, Text, etc.).

func (FormatOptions) Clone

func (o FormatOptions) Clone() FormatOptions

Clone creates a deep copy of FormatOptions. It returns a new FormatOptions instance with all fields copied from the original: - prefix for line starting content - lineEnding for line termination characters - indent for indentation string - pretty flag for human-readable output - args for format arguments This ensures that modifications to the clone don't affect the original options.

func (FormatOptions) Indent

func (o FormatOptions) Indent() string

Indent returns the string used for indentation.

func (FormatOptions) LineEnding

func (o FormatOptions) LineEnding() string

LineEnding returns the string used for line endings.

func (FormatOptions) Prefix

func (o FormatOptions) Prefix() string

Prefix returns the string to prepend to each line.

func (FormatOptions) Pretty

func (o FormatOptions) Pretty() bool

Pretty returns whether pretty formatting is enabled.

type HeaderOptions

type HeaderOptions = textproto.MIMEHeader

HeaderOptions is a type alias for textproto.MIMEHeader, providing standard HTTP header management with support for multiple values per key.

type JSONConfig

type JSONConfig struct {
	// Controls HTML character escaping
	EscapeHTML bool

	// Custom prefix for JSON output
	Prefix string

	// Custom indentation for JSON output
	Indent string

	// JSONP function name (if empty, standard JSON is used)
	Padding string
}

JSONConfig defines configuration for JSON renderer. It provides JSON-specific settings that are set during initialization.

type Options

type Options struct {
	// contains filtered or unexported fields
}

Options defines configuration settings for rendering operations. It provides control over formatting, content type, encoding and other rendering aspects.

func NewOptions

func NewOptions() *Options

NewOptions creates a new Options instance with default values.

func (*Options) Clone

func (o *Options) Clone() *Options

Clone creates a deep copy of the Options instance. It returns a new Options pointer with all fields deeply copied to ensure modifications to the clone do not affect the original:

  • Simple fields (name, timeout) are copied directly
  • Format options are cloned using FormatOptions.Clone()
  • Parameters map is recreated with copied key-value pairs
  • Headers are recreated with copied values for each key

This method is useful when you need to modify options without affecting the original configuration or when sharing options across different renders.

func (*Options) ContentType

func (o *Options) ContentType() string

ContentType returns the content type from headers, if any.

func (*Options) Format

func (o *Options) Format() FormatOptions

Format returns the formatting options configured for this renderer. It provides access to formatting settings like:

  • Indentation
  • Line endings
  • Pretty printing configuration
  • Format arguments for template rendering

The returned FormatOptions controls how the rendered output will be formatted, allowing consistent formatting across different render operations.

func (*Options) Header

func (o *Options) Header() HeaderOptions

Header returns the header options for the rendering operation. Headers can be used to set content type, charset, and other HTTP headers.

func (*Options) Name

func (o *Options) Name() string

Name returns the configured template name or identifier. An empty string means no specific template name is set.

func (*Options) Params

func (o *Options) Params() map[string]string

Params returns the map of additional parameters. These parameters can be used to pass custom configuration to renderers.

func (*Options) Reset

func (o *Options) Reset() *Options

Reset restores all options to their default values. It ensures that all fields have appropriate defaults and allocates necessary resources like maps.

func (*Options) String

func (o *Options) String() string

String returns a human-readable representation of the current options configuration. This includes template name, timeout, format settings, headers, and parameters.

func (*Options) Timeout

func (o *Options) Timeout() time.Duration

Timeout returns the configured rendering timeout duration. A zero duration means no timeout is set.

func (*Options) Use

func (o *Options) Use(opts ...func(*Options)) *Options

Use applies one or more option functions to the Options instance. It validates the options after all functions are applied.

type Renderer

type Renderer interface {
	// Render writes the formatted representation of data to the writer.
	// It uses the provided options to configure the rendering process.
	// This is a convenience method that uses a background context.
	Render(w io.Writer, data any, opts ...func(*Options)) error

	// RenderContext is similar to Render but accepts a context for
	// cancellation, timeouts, and other context-based features.
	// The context allows controlling the rendering lifecycle.
	RenderContext(ctx context.Context, w io.Writer, data any, opts ...func(*Options)) error
}

Renderer defines a common interface for all renderers in the system. It provides a unified way to render content with or without context, using functional options for configuration.

The interface is designed to be simple yet flexible, allowing different types of renderers (JSON, XML, HTML, etc.) to share the same API while implementing their specific rendering logic.

func CSV

func CSV() Renderer

CSV creates a new CSV renderer with default configuration: - Comma as delimiter - Standard line endings based on encoding/csv defaults This is the recommended constructor for most use cases.

func JSON

func JSON() Renderer

JSON creates a new JSONRenderer with safe default configuration: - HTML escaping enabled for web safety - Standard 2-space indentation This is the recommended constructor for most use cases.

func NewJSON

func NewJSON(c JSONConfig) Renderer

NewJSON creates a JSONRenderer with custom configuration. Use this when you need specific JSON behaviors different from defaults.

func NewXML

func NewXML(c XMLConfig) Renderer

NewXML creates a XMLRenderer with custom configuration. Use this when you need specific XML behaviors different from defaults.

func Text

func Text() Renderer

Text creates a new TextRenderer instance configured with default options. The renderer uses text/plain content type by default which can be overridden using render options.

func XML

func XML() Renderer

XML creates a new XMLRenderer with safe default configuration. Default settings include: - Standard 2-space indentation - XML header included This is the recommended constructor for most use cases.

type XMLConfig

type XMLConfig struct {
	// Prefix specifies the string to prepend at the start of each line.
	// This is particularly useful when embedding XML within another format.
	Prefix string

	// Indent specifies the string used for each level of indentation.
	// Common values are spaces ("  ") or tabs ("\t").
	Indent string

	// Header controls whether to include the XML declaration at the start.
	// When true, adds <?xml version="1.0" encoding="UTF-8"?>.
	Header bool
}

XMLConfig defines configuration options for XML rendering. It allows customization of escaping, indentation, and XML header inclusion.

Directories

Path Synopsis
Package tmpl provides a flexible template rendering system that supports both text and HTML templates.
Package tmpl provides a flexible template rendering system that supports both text and HTML templates.

Jump to

Keyboard shortcuts

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