1
0
mirror of https://github.com/strongdm/comply synced 2024-09-28 22:30:59 +00:00

Add pandoc multi file output capability

This commit is contained in:
Mike Tocci 2021-08-03 18:19:24 -04:00
parent 04fd6d351b
commit f60d1e94c0
6 changed files with 47 additions and 1503 deletions

View File

@ -29,3 +29,8 @@ tickets:
# domain: https://gitlab.example.com:443/ # or https://gitlab.com/ # domain: https://gitlab.example.com:443/ # or https://gitlab.com/
# token: token-here # token: token-here
# repo: full-slug/of-project # repo: full-slug/of-project
# Common file types output by pandoc. Examples here: https://pandoc.org/MANUAL.html#general-options
outputs:
- pdf
- docx

View File

@ -38,6 +38,20 @@ type Project struct {
FilePrefix string `yaml:"filePrefix"` FilePrefix string `yaml:"filePrefix"`
Tickets map[string]interface{} `yaml:"tickets"` Tickets map[string]interface{} `yaml:"tickets"`
ApprovedBranch string `yaml:"approvedBranch"` ApprovedBranch string `yaml:"approvedBranch"`
DocOutputs []string `yaml:"outputs"`
}
// Get outputfile extensions from yaml but set default as pdf for backwards
// compatibility with legacy yaml files
func GetFileExtensions() []string {
fileExtensions := Config().DocOutputs
if len(fileExtensions) == 0 {
fileExtensions = append(fileExtensions, "pdf")
return fileExtensions
} else {
return fileExtensions
}
} }
// SetPandoc records pandoc availability during initialization // SetPandoc records pandoc availability during initialization

View File

@ -91,6 +91,7 @@ func ReadStandards() ([]*Standard, error) {
} }
// ReadNarratives loads narrative descriptions from the filesystem. // ReadNarratives loads narrative descriptions from the filesystem.
// remove pdf file ending and place that logic in document.go
func ReadNarratives() ([]*Document, error) { func ReadNarratives() ([]*Document, error) {
var narratives []*Document var narratives []*Document
@ -109,7 +110,7 @@ func ReadNarratives() ([]*Document, error) {
n.Body = mdmd.body n.Body = mdmd.body
n.FullPath = f.FullPath n.FullPath = f.FullPath
n.ModifiedAt = f.Info.ModTime() n.ModifiedAt = f.Info.ModTime()
n.OutputFilename = fmt.Sprintf("%s-%s.pdf", config.Config().FilePrefix, n.Acronym) n.OutputFilename = fmt.Sprintf("%s-%s.", config.Config().FilePrefix, n.Acronym)
narratives = append(narratives, n) narratives = append(narratives, n)
} }
@ -141,6 +142,7 @@ func ReadProcedures() ([]*Procedure, error) {
} }
// ReadPolicies loads policy documents from the filesystem. // ReadPolicies loads policy documents from the filesystem.
// remove pdf file ending and place that logic in ...
func ReadPolicies() ([]*Document, error) { func ReadPolicies() ([]*Document, error) {
var policies []*Document var policies []*Document
@ -159,7 +161,7 @@ func ReadPolicies() ([]*Document, error) {
p.Body = mdmd.body p.Body = mdmd.body
p.FullPath = f.FullPath p.FullPath = f.FullPath
p.ModifiedAt = f.Info.ModTime() p.ModifiedAt = f.Info.ModTime()
p.OutputFilename = fmt.Sprintf("%s-%s.pdf", config.Config().FilePrefix, p.Acronym) p.OutputFilename = fmt.Sprintf("%s-%s.", config.Config().FilePrefix, p.Acronym)
policies = append(policies, p) policies = append(policies, p)
} }

View File

@ -18,6 +18,10 @@ import (
"github.com/strongdm/comply/internal/model" "github.com/strongdm/comply/internal/model"
) )
// Pull array of file extensions from config
// for each pdf passed in, iterate other extensions and pass to pandoc.
// This way, all types will be rendered BEFORE the system deletes the markdown preprocessed file
// TODO: refactor and eliminate duplication among narrative, policy renderers // TODO: refactor and eliminate duplication among narrative, policy renderers
func renderToFilesystem(wg *sync.WaitGroup, errOutputCh chan error, data *renderData, doc *model.Document, live bool) { func renderToFilesystem(wg *sync.WaitGroup, errOutputCh chan error, data *renderData, doc *model.Document, live bool) {
// only files that have been touched // only files that have been touched
@ -31,6 +35,7 @@ func renderToFilesystem(wg *sync.WaitGroup, errOutputCh chan error, data *render
defer wg.Done() defer wg.Done()
outputFilename := p.OutputFilename outputFilename := p.OutputFilename
// save preprocessed markdown // save preprocessed markdown
err := preprocessDoc(data, p, filepath.Join(".", "output", outputFilename+".md")) err := preprocessDoc(data, p, filepath.Join(".", "output", outputFilename+".md"))
if err != nil { if err != nil {
@ -38,7 +43,19 @@ func renderToFilesystem(wg *sync.WaitGroup, errOutputCh chan error, data *render
return return
} }
pandoc(outputFilename, errOutputCh) // get list of output file types from config
fileExtensions := config.GetFileExtensions()
for i := range fileExtensions {
// pass file extension and let pandoc handle output format
pandoc(outputFilename, fileExtensions[i], errOutputCh)
rel, err := filepath.Rel(config.ProjectRoot(), p.FullPath)
if err != nil {
rel = p.FullPath
}
fmt.Printf("%s -> %s\n", rel, filepath.Join("output", p.OutputFilename+fileExtensions[i]))
}
// remove preprocessed markdown // remove preprocessed markdown
err = os.Remove(filepath.Join(".", "output", outputFilename+".md")) err = os.Remove(filepath.Join(".", "output", outputFilename+".md"))
@ -47,11 +64,6 @@ func renderToFilesystem(wg *sync.WaitGroup, errOutputCh chan error, data *render
return return
} }
rel, err := filepath.Rel(config.ProjectRoot(), p.FullPath)
if err != nil {
rel = p.FullPath
}
fmt.Printf("%s -> %s\n", rel, filepath.Join("output", p.OutputFilename))
}(doc) }(doc)
} }

View File

@ -16,18 +16,18 @@ import (
var pandocArgs = []string{"-f", "markdown+smart", "--toc", "-N", "--template", "templates/default.latex", "-o"} var pandocArgs = []string{"-f", "markdown+smart", "--toc", "-N", "--template", "templates/default.latex", "-o"}
func pandoc(outputFilename string, errOutputCh chan error) { func pandoc(outputFilename string, fileExtension string, errOutputCh chan error) {
if config.WhichPandoc() == config.UsePandoc { if config.WhichPandoc() == config.UsePandoc {
err := pandocPandoc(outputFilename) err := pandocPandoc(outputFilename, fileExtension)
if err != nil { if err != nil {
errOutputCh <- err errOutputCh <- err
} }
} else { } else {
dockerPandoc(outputFilename, errOutputCh) dockerPandoc(outputFilename, fileExtension, errOutputCh)
} }
} }
func dockerPandoc(outputFilename string, errOutputCh chan error) { func dockerPandoc(outputFilename string, fileExtension string, errOutputCh chan error) {
pandocCmd := append(pandocArgs, fmt.Sprintf("/source/output/%s", outputFilename), fmt.Sprintf("/source/output/%s.md", outputFilename)) pandocCmd := append(pandocArgs, fmt.Sprintf("/source/output/%s", outputFilename), fmt.Sprintf("/source/output/%s.md", outputFilename))
ctx := context.Background() ctx := context.Background()
cli, err := client.NewEnvClient() cli, err := client.NewEnvClient()
@ -90,8 +90,8 @@ func dockerPandoc(outputFilename string, errOutputCh chan error) {
} }
// 🐼 // 🐼
func pandocPandoc(outputFilename string) error { func pandocPandoc(outputFilename string, fileExtension string) error {
cmd := exec.Command("pandoc", append(pandocArgs, fmt.Sprintf("output/%s", outputFilename), fmt.Sprintf("output/%s.md", outputFilename))...) cmd := exec.Command("pandoc", append(pandocArgs, fmt.Sprintf("output/%s%s", outputFilename, fileExtension), fmt.Sprintf("output/%s.md", outputFilename))...)
outputRaw, err := cmd.CombinedOutput() outputRaw, err := cmd.CombinedOutput()
if err != nil { if err != nil {
fmt.Println(string(outputRaw)) fmt.Println(string(outputRaw))

File diff suppressed because one or more lines are too long