Skip to content

NewTemplateFileSystem for fileb0x (similar to vfsgen, assetfs, etc) #3

Description

@coolaj86

I needed to use macaron.Render with fileb0x instead of bindata. I think that this code will be helpful for anyone who might need to use vfsgen, packr, statik, rice and other bindata-style systems.

package router

import (
	"bytes"
	"fmt"
	"io"
	"path/filepath"

	"code.example.com/me/go-static"

	"gopkg.in/macaron.v1"
)

// Replace the one from macaron.Render since the files field is private
// TplFileSystem implements TemplateFileSystem interface.
type TplFileSystem struct {
	files []macaron.TemplateFile
}

// NewTemplateFileSystem creates new template file system with given options.
func NewTemplateFileSystem(lastDir string, exts ...string) macaron.TemplateFileSystem {
	fs := TplFileSystem{}
	fs.files = make([]macaron.TemplateFile, 0, 10)
	if 0 == len(exts) {
		exts = []string{".tmpl", ".html"}
	}

	// This is the fileb0x WalkDirs
	paths, _ := static.WalkDirs(lastDir, false)
	for _, path := range paths {
		r, err := filepath.Rel(lastDir, path)
		ext := macaron.GetExt(r)

		for _, extension := range exts {
			if ext != extension {
				continue
			}

			var data []byte
			// Loop over candidates of directory, break out once found.
			// The file always exists because it's inside the walk function,
			// and read original file is the worst case.
			path = filepath.Join(lastDir, r)
			data, err = static.ReadFile(path)
			if err != nil {
				panic(err)
			}

			name := filepath.ToSlash((r[0 : len(r)-len(ext)]))
			fs.files = append(fs.files, macaron.NewTplFile(name, data, ext))
		}
	}

	return fs
}

func (fs TplFileSystem) ListFiles() []macaron.TemplateFile {
	return fs.files
}

func (fs TplFileSystem) Get(name string) (io.Reader, error) {
	for i := range fs.files {
		if fs.files[i].Name()+fs.files[i].Ext() == name {
			return bytes.NewReader(fs.files[i].Data()), nil
		}
	}
	return nil, fmt.Errorf("file '%s' not found", name)
}

This could probably be updated to use a generic interface that would work with many different FileSystem implementations and be created as a PR. However, for now I'll just leave this an example that others can easily follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions