diff --git a/config/config.go b/config/config.go index f10a55b..5d940de 100644 --- a/config/config.go +++ b/config/config.go @@ -47,6 +47,11 @@ type KnownType struct { Link string `json:"link"` } +const ( + OutputModeSingle = "single" + OutputModeGroup = "group" +) + type Flags struct { Config string LogLevel string @@ -54,6 +59,7 @@ type Flags struct { Renderer string SourcePath string TemplatesDir string + OutputMode string MaxDepth int } diff --git a/main.go b/main.go index fb3908a..8844f1d 100644 --- a/main.go +++ b/main.go @@ -45,6 +45,7 @@ func main() { cmd.Flags().StringVar(&args.TemplatesDir, "templates-dir", "", "Path to the directory containing template files") cmd.Flags().StringVar(&args.Renderer, "renderer", "asciidoctor", "Renderer to use ('asciidoctor' or 'markdown')") cmd.Flags().StringVar(&args.OutputPath, "output-path", ".", "Path to output the rendered result") + cmd.Flags().StringVar(&args.OutputMode, "output-mode", "single", "Output mode to generate a single file or one file per group ('group' or 'single')") cmd.Flags().IntVar(&args.MaxDepth, "max-depth", 10, "Maximum recursion level for type discovery") cmd.Execute() diff --git a/renderer/asciidoctor.go b/renderer/asciidoctor.go index be144d5..ab22ac5 100644 --- a/renderer/asciidoctor.go +++ b/renderer/asciidoctor.go @@ -65,10 +65,7 @@ func (adr *AsciidoctorRenderer) Render(gvd []types.GroupVersionDetails) error { return err } - f, err := createOutFile(adr.conf.OutputPath, "out.asciidoc") - defer f.Close() - - return tmpl.ExecuteTemplate(f, mainTemplate, gvd) + return renderTemplate(tmpl, adr.conf, "asciidoc", gvd) } func (adr *AsciidoctorRenderer) ToFuncMap() template.FuncMap { diff --git a/renderer/markdown.go b/renderer/markdown.go index fd502fd..96a06d8 100644 --- a/renderer/markdown.go +++ b/renderer/markdown.go @@ -61,10 +61,7 @@ func (m *MarkdownRenderer) Render(gvd []types.GroupVersionDetails) error { return err } - f, err := createOutFile(m.conf.OutputPath, "out.md") - defer f.Close() - - return tmpl.ExecuteTemplate(f, mainTemplate, gvd) + return renderTemplate(tmpl, m.conf, "md", gvd) } func (m *MarkdownRenderer) ToFuncMap() template.FuncMap { diff --git a/renderer/renderer.go b/renderer/renderer.go index 28d98ab..3d89656 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -64,7 +64,46 @@ func combinedFuncMap(funcs ...funcMap) template.FuncMap { return m } -func createOutFile(outputPath string, defaultFileName string) (*os.File, error) { +// renderTemplate applies a given template to a set of GroupVersionDetails and writes the output to files, it supports +// two output modes as specified in the configuration: single mode or group mode. +// In single mode, all data is rendered into one output file. +// In group mode, separate files are created for each group. +func renderTemplate(tmpl *template.Template, conf *config.Config, fileExtension string, gvds []types.GroupVersionDetails) error { + switch conf.OutputMode { + case config.OutputModeSingle: + fileName := fmt.Sprintf("%s.%s", "out", fileExtension) + file, err := createOutFile(conf.OutputPath, false, fileName) + defer file.Close() + if err != nil { + return err + } + + if err := tmpl.ExecuteTemplate(file, mainTemplate, gvds); err != nil { + return err + } + + case config.OutputModeGroup: + for _, gvd := range gvds { + fileName := fmt.Sprintf("%s.%s", gvd.Group, fileExtension) + file, err := createOutFile(conf.OutputPath, true, fileName) + defer file.Close() + if err != nil { + return err + } + + if err := tmpl.ExecuteTemplate(file, mainTemplate, []types.GroupVersionDetails{gvd}); err != nil { + return err + } + } + } + + return nil +} + +// createOutFile creates the file pointed to by outputPath if it does not exist, or if it exists and is a directory, +// then creates a file in the directory using the given defaultFilename. If expectedDir is true, outputPath must be an +// existing directory where defaultFileName is created. +func createOutFile(outputPath string, expectedDir bool, defaultFileName string) (*os.File, error) { finfo, err := os.Stat(outputPath) if err != nil && !os.IsNotExist(err) { return nil, err @@ -72,6 +111,8 @@ func createOutFile(outputPath string, defaultFileName string) (*os.File, error) if finfo != nil && finfo.IsDir() { outputPath = filepath.Join(outputPath, defaultFileName) + } else if expectedDir { + return nil, fmt.Errorf("output path must point to an existing directory") } return os.Create(outputPath)