package config import ( "fmt" "reflect" "github.com/imdario/mergo" ) // MapString is a map[string]interface{} which always unmarsahls yaml to map[string]interface{} type MapString map[string]interface{} // UnmarshalYAML handles all maps as map[string]interface{} for later JSON // see https://github.com/elastic/beats/blob/6435194af9f42cbf778ca0a1a92276caf41a0da8/libbeat/common/mapstr.go func (ms *MapString) UnmarshalYAML(unmarshal func(interface{}) error) error { var result map[interface{}]interface{} err := unmarshal(&result) if err != nil { return err } *ms = cleanUpInterfaceMap(result) return nil } func cleanUpInterfaceArray(in []interface{}) []interface{} { result := make([]interface{}, len(in)) for i, v := range in { result[i] = cleanUpMapValue(v) } return result } func cleanUpInterfaceMap(in map[interface{}]interface{}) MapString { result := make(MapString) for k, v := range in { result[fmt.Sprintf("%v", k)] = cleanUpMapValue(v) } return result } func cleanUpMapValue(v interface{}) interface{} { switch v := v.(type) { case []interface{}: return cleanUpInterfaceArray(v) case map[interface{}]interface{}: return cleanUpInterfaceMap(v) case string: return v default: return fmt.Sprintf("%v", v) } } // CollectionConfig describes a collection type CollectionConfig struct { Name *string `yaml:"Name"` EntriesJSON *string `yaml:"EntriesJSON"` NavTemplate *struct { GoTo string `yaml:"GoTo"` Navname string `yaml:"Navname"` Body string `yaml:"Body"` DataKey string `yaml:"DataKey"` Hidden bool `yaml:"Hidden"` Template string `yaml:"Template"` Recursive bool `yaml:"Recursive"` } `yaml:"NavTemplate"` } // ThisPathConfig is struct for This in paths yaml type ThisPathConfig struct { Navname *string `yaml:"Navname"` GoTo *string `yaml:"GoTo"` Collections []*CollectionConfig `yaml:"Collections"` Data MapString `yaml:"Data"` } // IndexConfig describes index input and output file type IndexConfig struct { InputFile *string `yaml:"InputFile"` InputString *string `yaml:"InputString"` OutputFile *string `yaml:"OutputFile"` } // MetaData describes meta data for current site/tree node type MetaData struct { Title *string `yaml:"Title"` Description *string `yaml:"Description"` Keywords *string `yaml:"Keywords"` } // DirnameConfig describes how to handle directory names type DirnameConfig struct { Strip *string `yaml:"Strip"` IgnoreForNav *string `yaml:"IgnoreForNav"` } // FilenameConfig describes how to handle filenames type FilenameConfig struct { Strip *string `yaml:"Strip"` Ignore *string `yaml:"Ignore"` OutputExtension *string `yaml:"OutputExtension"` } // MarkdownConfig describes markdown handling type MarkdownConfig struct { ChromaRenderer *bool `yaml:"ChromaRenderer"` ChromaStyle *string `yaml:"ChromaStyle"` } // ImagingConfig defines parameter for imaging processing type ImagingConfig struct { Width int `yaml:"Width"` Height int `yaml:"Height"` Process string `yaml:"Process"` Anchor string `yaml:"Anchor"` Quality int `yaml:"Quality"` Filename string `yaml:"-"` Format string `yaml:"-"` } // PathConfig of subdir type PathConfig struct { This ThisPathConfig `yaml:"This"` Template *string `yaml:"Template"` Index *IndexConfig `yaml:"Index"` Meta *MetaData `yaml:"Meta"` Path *DirnameConfig `yaml:"Path"` Filename *FilenameConfig `yaml:"Filename"` Markdown *MarkdownConfig `yaml:"Markdown"` Imaging *ImagingConfig `yaml:"Imaging"` Data MapString `yaml:"Data"` } // PathConfigTree is complete config tree of content dir type PathConfigTree struct { InputPath string OutputPath string Hidden bool // for collections which are not part of the navigation ColMap MapString InputFiles []string OtherFiles []string Config *PathConfig Sub []*PathConfigTree } type ptrTransformer struct{} func (t ptrTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { if typ.Kind() == reflect.Ptr { return func(dst, src reflect.Value) error { if dst.CanSet() { if dst.IsNil() { dst.Set(src) } } return nil } } return nil } // Merge merges 2 objects or maps func Merge(dst, src interface{}) error { return mergo.Merge(dst, src, mergo.WithTransformers(ptrTransformer{})) }