func (p Pipeline) Run(input InputFunc, output OutputFunc, verbose bool) error {
	epubdir, err := ioutil.TempDir("", "epub-*")
	if err != nil {
		return util.Wrap(err, "could not create temp dir")
	}
	defer os.RemoveAll(epubdir)
	if verbose {
		fmt.Printf("Opening input\n")
	}
	if err := input(epubdir); err != nil {
		return util.Wrap(err, "could not run input")
	}
	if _, err := os.Stat(filepath.Join(epubdir, "META-INF", "container.xml")); err != nil {
		return errors.New("could not access META-INF/container.xml")
	}
	for i, transform := range p {
		if verbose {
			if transform.Desc != "" {
				fmt.Printf("Running transform %d: %s\n", i+1, transform.Desc)
			} else {
				fmt.Printf("Running transform %d\n", i+1)
			}
		}
		if transform.OPF != nil {
			if err := transformOPF(epubdir, transform.OPF); err != nil {
				return util.Wrap(err, "could not run opf transform (%s)", transform.Desc)
			}
		}
		if transform.OPFDoc != nil {
			if err := transformOPFDoc(epubdir, transform.OPFDoc); err != nil {
				return util.Wrap(err, "could not run opfdoc transform (%s)", transform.Desc)
			}
		}
		if transform.Raw != nil {
			if err := transform.Raw(epubdir); err != nil {
				return util.Wrap(err, "could not run raw transform (%s)", transform.Desc)
			}
		}
		if transform.ContentFile != nil {
			if err := transformContent(epubdir, transform.ContentFile); err != nil {
				return util.Wrap(err, "could not run content transform (%s)", transform.Desc)
			}
		}
		if transform.ContentDoc != nil {
			if err := transformContentDoc(epubdir, transform.ContentDoc); err != nil {
				return util.Wrap(err, "could not run contentdoc transform (%s)", transform.Desc)
			}
		}
	}
	if output == nil {
		if verbose {
			fmt.Printf("Skipping output\n")
		}
		return nil
	}
	if verbose {
		fmt.Printf("Writing output\n")
	}
	if err := output(epubdir); err != nil {
		return util.Wrap(err, "could not run output")
	}
	return nil
}
Run runs the transform pipeline.
package epubtransform
import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"github.com/PuerkitoBio/goquery"
	"github.com/beevik/etree"
	"github.com/pgaskin/epubtool/util"
)
type Pipeline []Transform
type InputFunc func(epubdir string) error
type OutputFunc func(epubdir string) error
type Transform struct {
	Desc        string
	OPF         func(opf string) (newOPF string, err error)
	OPFDoc      func(opf *etree.Document) error
	Raw         func(epubdir string) error
	ContentFile func(relpath, html string) (newHTML string, err error)
	ContentDoc  func(relpath string, doc *goquery.Document) error  
}
func New(transforms ...Transform) Pipeline {
	return Pipeline(transforms)
}