You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
3.2 KiB

package mime
import (
"encoding/json"
"fmt"
"go/format"
"io/ioutil"
"os"
"path"
"text/template"
)
type Config struct {
Source string
Mimes map[string][]string
MimePrefix string
MimeTpl string
MimeResult string
MimePackage string
Extensions map[string][]string
ExtPrefix string
ExtTpl string
ExtResult string
ExtPackage string
}
func WithExtTpl(name string) Option {
return func(c *Config) {
c.ExtTpl = name
}
}
func WithExtPacakge(name string) Option {
return func(c *Config) {
c.ExtPackage = name
}
}
func WithExtResult(name string) Option {
return func(c *Config) {
c.ExtResult = name
}
}
func WithMimeTpl(name string) Option {
return func(c *Config) {
c.MimeTpl = name
}
}
func WithMimePackage(name string) Option {
return func(c *Config) {
c.MimePackage = name
}
}
func WithMimeResult(name string) Option {
return func(c *Config) {
c.MimeResult = name
}
}
type Option func(*Config)
func funcMap() template.FuncMap {
return template.FuncMap{
"name": VarName,
"value": Value,
}
}
func Generate(fileName string, opts ...Option) error {
cfg := Config{
Source: fileName,
ExtPrefix: "Ext",
ExtTpl: "mime/tpl/extension.text.tmpl",
ExtResult: "extension.go",
Extensions: make(map[string][]string),
ExtPackage: "mime",
MimeTpl: "mime/tpl/mime.text.tmpl",
Mimes: make(map[string][]string),
MimePrefix: "",
MimeResult: "mime.go",
MimePackage: "mime",
}
for _, opt := range opts {
opt(&cfg)
}
data, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("read file:%w", err)
}
if err := json.Unmarshal(data, &cfg.Mimes); err != nil {
return fmt.Errorf("unmarshal:%w", err)
}
cfg.Extensions = extensions(cfg.Mimes)
template, err := template.New("mimes").Funcs(funcMap()).ParseFiles(cfg.ExtTpl, cfg.MimeTpl)
if err != nil {
return fmt.Errorf("ext template:%w", err)
}
extFile, err := os.Create(cfg.ExtResult)
if err != nil {
return fmt.Errorf("ext file:%w", err)
}
if err := template.ExecuteTemplate(extFile, path.Base(cfg.ExtTpl), cfg); err != nil {
return fmt.Errorf("ext execute:%w", err)
}
if err := Format(extFile.Name()); err != nil {
return fmt.Errorf("format ext:%w", err)
}
mimeFile, err := os.Create(cfg.MimeResult)
if err != nil {
return fmt.Errorf("mime file:%w", err)
}
if err := template.ExecuteTemplate(mimeFile, path.Base(cfg.MimeTpl), cfg); err != nil {
return fmt.Errorf("mime execute:%w", err)
}
if err := Format(mimeFile.Name()); err != nil {
return fmt.Errorf("format mime:%w", err)
}
return nil
}
// Format file and write it.
func Format(name string) error {
in, err := ioutil.ReadFile(name)
if err != nil {
return err
}
out, err := format.Source(in)
if err != nil {
return err
}
file, err := os.Create(name)
if err != nil {
return fmt.Errorf("ext file:%w", err)
}
if _, err := file.Write(out); err != nil {
return fmt.Errorf("write:%w", err)
}
return nil
}
func extensions(mimes map[string][]string) map[string][]string {
out := make(map[string][]string)
for mime, exts := range mimes {
for _, ext := range exts {
if _, ok := out[ext]; ok {
out[ext] = append(out[ext], mime)
continue
}
out[ext] = []string{ext}
}
}
return out
}