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 }