github.com/olliephillips/hugo@v0.42.2/deps/deps.go (about) 1 package deps 2 3 import ( 4 "io/ioutil" 5 "log" 6 "os" 7 "time" 8 9 "github.com/gohugoio/hugo/config" 10 "github.com/gohugoio/hugo/helpers" 11 "github.com/gohugoio/hugo/hugofs" 12 "github.com/gohugoio/hugo/langs" 13 "github.com/gohugoio/hugo/metrics" 14 "github.com/gohugoio/hugo/output" 15 "github.com/gohugoio/hugo/source" 16 "github.com/gohugoio/hugo/tpl" 17 jww "github.com/spf13/jwalterweatherman" 18 ) 19 20 // Deps holds dependencies used by many. 21 // There will be normally only one instance of deps in play 22 // at a given time, i.e. one per Site built. 23 type Deps struct { 24 // The logger to use. 25 Log *jww.Notepad `json:"-"` 26 27 // Used to log errors that may repeat itself many times. 28 DistinctErrorLog *helpers.DistinctLogger 29 30 // The templates to use. This will usually implement the full tpl.TemplateHandler. 31 Tmpl tpl.TemplateFinder `json:"-"` 32 33 // The file systems to use. 34 Fs *hugofs.Fs `json:"-"` 35 36 // The PathSpec to use 37 *helpers.PathSpec `json:"-"` 38 39 // The ContentSpec to use 40 *helpers.ContentSpec `json:"-"` 41 42 // The SourceSpec to use 43 SourceSpec *source.SourceSpec `json:"-"` 44 45 // The configuration to use 46 Cfg config.Provider `json:"-"` 47 48 // The translation func to use 49 Translate func(translationID string, args ...interface{}) string `json:"-"` 50 51 Language *langs.Language 52 53 // All the output formats available for the current site. 54 OutputFormatsConfig output.Formats 55 56 templateProvider ResourceProvider 57 WithTemplate func(templ tpl.TemplateHandler) error `json:"-"` 58 59 translationProvider ResourceProvider 60 61 Metrics metrics.Provider 62 63 // Timeout is configurable in site config. 64 Timeout time.Duration 65 } 66 67 // ResourceProvider is used to create and refresh, and clone resources needed. 68 type ResourceProvider interface { 69 Update(deps *Deps) error 70 Clone(deps *Deps) error 71 } 72 73 // TemplateHandler returns the used tpl.TemplateFinder as tpl.TemplateHandler. 74 func (d *Deps) TemplateHandler() tpl.TemplateHandler { 75 return d.Tmpl.(tpl.TemplateHandler) 76 } 77 78 // LoadResources loads translations and templates. 79 func (d *Deps) LoadResources() error { 80 // Note that the translations need to be loaded before the templates. 81 if err := d.translationProvider.Update(d); err != nil { 82 return err 83 } 84 85 if err := d.templateProvider.Update(d); err != nil { 86 return err 87 } 88 89 if th, ok := d.Tmpl.(tpl.TemplateHandler); ok { 90 th.PrintErrors() 91 } 92 93 return nil 94 } 95 96 // New initializes a Dep struct. 97 // Defaults are set for nil values, 98 // but TemplateProvider, TranslationProvider and Language are always required. 99 func New(cfg DepsCfg) (*Deps, error) { 100 var ( 101 logger = cfg.Logger 102 fs = cfg.Fs 103 ) 104 105 if cfg.TemplateProvider == nil { 106 panic("Must have a TemplateProvider") 107 } 108 109 if cfg.TranslationProvider == nil { 110 panic("Must have a TranslationProvider") 111 } 112 113 if cfg.Language == nil { 114 panic("Must have a Language") 115 } 116 117 if logger == nil { 118 logger = jww.NewNotepad(jww.LevelError, jww.LevelError, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) 119 } 120 121 if fs == nil { 122 // Default to the production file system. 123 fs = hugofs.NewDefault(cfg.Language) 124 } 125 126 ps, err := helpers.NewPathSpec(fs, cfg.Language) 127 128 if err != nil { 129 return nil, err 130 } 131 132 contentSpec, err := helpers.NewContentSpec(cfg.Language) 133 if err != nil { 134 return nil, err 135 } 136 137 sp := source.NewSourceSpec(ps, fs.Source) 138 139 timeoutms := cfg.Language.GetInt("timeout") 140 if timeoutms <= 0 { 141 timeoutms = 3000 142 } 143 144 distinctErrorLogger := helpers.NewDistinctLogger(logger.ERROR) 145 146 d := &Deps{ 147 Fs: fs, 148 Log: logger, 149 DistinctErrorLog: distinctErrorLogger, 150 templateProvider: cfg.TemplateProvider, 151 translationProvider: cfg.TranslationProvider, 152 WithTemplate: cfg.WithTemplate, 153 PathSpec: ps, 154 ContentSpec: contentSpec, 155 SourceSpec: sp, 156 Cfg: cfg.Language, 157 Language: cfg.Language, 158 Timeout: time.Duration(timeoutms) * time.Millisecond, 159 } 160 161 if cfg.Cfg.GetBool("templateMetrics") { 162 d.Metrics = metrics.NewProvider(cfg.Cfg.GetBool("templateMetricsHints")) 163 } 164 165 return d, nil 166 } 167 168 // ForLanguage creates a copy of the Deps with the language dependent 169 // parts switched out. 170 func (d Deps) ForLanguage(l *langs.Language) (*Deps, error) { 171 var err error 172 173 d.PathSpec, err = helpers.NewPathSpecWithBaseBaseFsProvided(d.Fs, l, d.BaseFs) 174 if err != nil { 175 return nil, err 176 } 177 178 d.ContentSpec, err = helpers.NewContentSpec(l) 179 if err != nil { 180 return nil, err 181 } 182 183 d.Cfg = l 184 d.Language = l 185 186 if err := d.translationProvider.Clone(&d); err != nil { 187 return nil, err 188 } 189 190 if err := d.templateProvider.Clone(&d); err != nil { 191 return nil, err 192 } 193 194 return &d, nil 195 196 } 197 198 // DepsCfg contains configuration options that can be used to configure Hugo 199 // on a global level, i.e. logging etc. 200 // Nil values will be given default values. 201 type DepsCfg struct { 202 203 // The Logger to use. 204 Logger *jww.Notepad 205 206 // The file systems to use 207 Fs *hugofs.Fs 208 209 // The language to use. 210 Language *langs.Language 211 212 // The configuration to use. 213 Cfg config.Provider 214 215 // Template handling. 216 TemplateProvider ResourceProvider 217 WithTemplate func(templ tpl.TemplateHandler) error 218 219 // i18n handling. 220 TranslationProvider ResourceProvider 221 222 // Whether we are in running (server) mode 223 Running bool 224 }