laminate

package module
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2025 License: MIT Imports: 17 Imported by: 0

README

laminate

Test Status Coverage Status MIT License PkgGoDev

A command-line bridge tool that orchestrates external image generation commands to convert text/code strings to images.

[!IMPORTANT] laminate itself does not generate images. Instead, it acts as a bridge that routes input text to appropriate external tools (like qrencode, silicon, mmdc, convert, etc.) based on configurable patterns and manages the execution flow.

How It Works

  1. Input: Reads text from stdin and language specification via --lang flag or CODEBLOCK_LANG environment variable
  2. Routing: Matches the language against configured patterns to select the appropriate external command
  3. Execution: Runs the selected external command with proper input/output handling
  4. Output: Returns the generated image data to stdout
  5. Caching: Optionally caches results to avoid re-executing expensive commands

Synopsis

# Generate QR code from text
echo "https://github.com/Songmu/laminate" | laminate --lang qr > qr.png

# Convert code to syntax-highlighted image
cat main.go | laminate --lang go > code.png

# Use with environment variable
export CODEBLOCK_LANG=python
cat script.py | laminate > python_code.png

# Generate image from any text (fallback to wildcard pattern)
echo "Hello World" | laminate --lang unknown > text.png

# Integration with k1LoW/deck for slide generation
deck apply -c laminate deck.md  # deck sets CODEBLOCK_LANG automatically

[!TIP] laminate works seamlessly with k1LoW/deck for generating slides with embedded code images. Use deck apply -c laminate deck.md to automatically convert code blocks in your markdown slides to images.

Prerequisites

[!IMPORTANT] You need to install the actual image generation tools that you want to use. laminate will fail if the required external commands are not available in your PATH.

The following are just examples of popular tools. You can use any command-line tool that can generate images - the choice is entirely up to you and your specific needs.

# For QR codes
brew install qrencode          # macOS
apt-get install qrencode       # Ubuntu/Debian

# For code syntax highlighting
cargo install silicon

# For Mermaid diagrams
npm install -g @mermaid-js/mermaid-cli

# For text-to-image (ImageMagick)
brew install imagemagick       # macOS
apt-get install imagemagick    # Ubuntu/Debian

Installation

Click to expand installation methods
# Install via Homebrew (macOS)
% brew install songmu/tap/laminate

# Install the latest version. (Install it into ./bin/ by default).
% curl -sfL https://raw.githubusercontent.com/Songmu/laminate/main/install.sh | sh -s

# Specify installation directory ($(go env GOPATH)/bin/) and version.
% curl -sfL https://raw.githubusercontent.com/Songmu/laminate/main/install.sh | sh -s -- -b $(go env GOPATH)/bin [vX.Y.Z]

# In alpine linux (as it does not come with curl by default)
% wget -O - -q https://raw.githubusercontent.com/Songmu/laminate/main/install.sh | sh -s [vX.Y.Z]

# go install
% go install github.com/Songmu/laminate/cmd/laminate@latest

Configuration

Create a configuration file at ~/.config/laminate/config.yaml (or $XDG_CONFIG_HOME/laminate/config.yaml):

cache: 1h
commands:
- lang: qr
  run: 'qrencode -o "{{output}}" -t png "{{input}}"'
  ext: png
- lang: mermaid
  run: 'mmdc -i - -o "{{output}}" --quiet'
  ext: png
- lang: '{go,rust,python,java,javascript,typescript}'
  run: 'silicon -l "{{lang}}" -o "{{output}}"'
  ext: png
- lang: '*'
  run: ['convert', '-background', 'white', '-fill', 'black', 'label:{{input}}', '{{output}}']
Configuration Schema
  • cache: Cache duration (e.g., 1h, 30m, 15s). Omit to disable caching.
  • commands: Array of command configurations.
    • lang: Language pattern (supports glob patterns and brace expansion)
    • run: Command to execute (string or array format)
    • ext: Output file extension (default: png)
    • shell: Shell to use for string commands (default: bash or sh)
Template Variables

You can use these variables in your commands as needed. The presence or absence of {{input}} and {{output}} determines how laminate handles I/O with the external command.

  • {{input}}: Input text from stdin
    • Present: Input passed as command-line argument
    • Absent: Input passed via stdin to the command
  • {{output}}: Output file path with extension from ext field (default: png)
    • Present: Command writes to this file, laminate reads it
    • Absent: Command writes to stdout, laminate captures it
  • {{lang}}: The language parameter specified by user

I/O Behavior Examples:

Variables Used Example Command How it works
Both qrencode -o "{{output}}" "{{input}}" Input as arg, output to file
Output only mmdc -i - -o "{{output}}" Input via stdin, output to file
Input only convert label:"{{input}}" png:- Input as arg, output to stdout
Neither some-converter Input via stdin, output to stdout
Language Matching

Commands are matched against the specified language in first-match-wins order from top to bottom in the configuration file. The matching process:

  1. Sequential matching: Each command's lang pattern is tested in the order they appear in the config
  2. First match wins: The first command whose lang pattern matches the specified language is used
  3. Pattern types: Supports exact matches, glob patterns, and brace expansion
    • Exact: go, python, rust
    • Brace expansion: {go,rust,python}, {js,ts}
    • Glob patterns: py*, *script, *
  4. Fallback: Typically a wildcard pattern * is placed last to catch unmatched languages

Example matching order:

commands:
  - lang: go            # 1st: Matches "go" exactly
  - lang: '{py,python}' # 2nd: Matches "py" or "python"
  - lang: 'js*'         # 3rd: Matches "js", "json", "jsx", etc.
  - lang: '*'           # 4th: Matches any remaining language

For language python: matches the 2nd command ({py,python}) and stops there.

[!TIP] Put more specific patterns at the top and general patterns (like *) at the bottom to ensure proper matching priority.

Environment Variables

  • CODEBLOCK_LANG: Language specification via environment variable (automatically set by k1LoW/deck)

Cache Management

Cache files are stored in ${XDG_CACHE_HOME:-~/.cache}/laminate/cache/ and keyed by input content + language + format.

# Set cache duration
cache: 2h

# Disable caching (omit cache field)
# cache: 0s

You can clear the cache by deleting the cache directory.

Usage Examples

Template Variable Behaviors
Commands with {{input}} and {{output}}
# Input passed as argument, output to file
- lang: qr
  run: 'qrencode -o "{{output}}" -t png "{{input}}"'
  ext: png
echo "https://example.com" | laminate --lang qr > qr.png
# Executes: qrencode -o "/tmp/laminate123.png" -t png "https://example.com"
Commands with {{output}} only (stdin input)
# Input via stdin, output to file
- lang: mermaid
  run: 'mmdc -i - -o "{{output}}" --quiet'
  ext: png
echo "graph TD; A-->B" | laminate --lang mermaid > diagram.png
# Executes: mmdc -i - -o "/tmp/laminate456.png" --quiet
# (with "graph TD; A-->B" passed via stdin)
Commands without {{output}} (stdout output)
# Input as argument, output via stdout
- lang: text
  run: 'convert -background white -fill black label:"{{input}}" png:-'
echo "Hello World" | laminate --lang text > text.png
# Executes: convert -background white -fill black label:"Hello World" png:-
# (image data read from command's stdout)
Commands without both variables (stdin to stdout)
# Input via stdin, output via stdout
- lang: simple
  run: 'some-image-converter'
echo "input text" | laminate --lang simple > output.png
# Executes: some-image-converter
# (with "input text" passed via stdin, image read from stdout)
Real-world Examples
QR Code Generation
echo "https://example.com" | laminate --lang qr > qr.png
Code Syntax Highlighting
# Using --lang flag (highest priority)
cat main.go | laminate --lang go > code.png

# Using environment variable
export CODEBLOCK_LANG=python
cat script.py | laminate > highlighted.png

# Empty language (uses first matching pattern)
cat README.md | laminate --lang "" > readme.png

[!NOTE] Priority: --lang flag > CODEBLOCK_LANG environment variable > empty string

Mermaid Diagrams
cat << EOF | laminate --lang mermaid > diagram.png
graph TD
    A[Start] --> B[Process]
    B --> C[End]
EOF

Author

Songmu

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExecuteWithCache

func ExecuteWithCache(ctx context.Context, config *Config, lang, input string, output io.Writer) error

ExecuteWithCache executes a command with caching support

func ExpandTemplate

func ExpandTemplate(template string, vars map[string]string) (string, error)

ExpandTemplate expands template variables in a command string

func Run

func Run(ctx context.Context, argv []string, outStream, errStream io.Writer) error

Run the laminate

Types

type Cache

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

Cache manages the cache for laminate

func NewCache

func NewCache(duration time.Duration) *Cache

NewCache creates a new cache instance

func (*Cache) Clean

func (c *Cache) Clean() error

Clean removes expired cache files

func (*Cache) Get

func (c *Cache) Get(lang, input, ext string) ([]byte, bool)

Get retrieves cached data if it exists and is not expired

func (*Cache) Set

func (c *Cache) Set(lang, input, ext string, data []byte) error

Set stores data in cache

type Command

type Command struct {
	Lang  string     `yaml:"lang"`
	Run   RunCommand `yaml:"run"`
	Ext   string     `yaml:"ext"`
	Shell string     `yaml:"shell"`
}

Command represents a single command configuration

func FindMatchingCommand

func FindMatchingCommand(commands []*Command, lang string) (*Command, error)

FindMatchingCommand finds the first command that matches the given language

func (*Command) GetExt

func (cmd *Command) GetExt() string

GetExt returns the file extension for the output

type Config

type Config struct {
	Cache    time.Duration `yaml:"cache"`
	Commands []*Command    `yaml:"commands"`
}

Config represents the configuration for laminate

func LoadConfig

func LoadConfig() (*Config, error)

LoadConfig loads the configuration from the config file

type Executor

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

Executor handles command execution

func (*Executor) Execute

func (e *Executor) Execute(ctx context.Context) ([]byte, error)

Execute runs the command and returns the output

type RunCommand

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

RunCommand represents a command that can be either a string or []string

func (*RunCommand) Array

func (r *RunCommand) Array() []string

Array returns the command as []string (only valid if IsArray() == true)

func (*RunCommand) IsArray

func (r *RunCommand) IsArray() bool

IsArray returns true if the command is an array

func (*RunCommand) String

func (r *RunCommand) String() string

String returns the command as string (only valid if IsArray() == false)

func (*RunCommand) UnmarshalYAML

func (r *RunCommand) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml.Unmarshaler

Directories

Path Synopsis
cmd
laminate command

Jump to

Keyboard shortcuts

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