2020-09-12 14:06:28 +01:00
|
|
|
package helpers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2020-09-13 14:24:29 +01:00
|
|
|
"io"
|
2020-09-12 14:06:28 +01:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2020-09-13 14:24:29 +01:00
|
|
|
"os/exec"
|
|
|
|
"strings"
|
2020-09-12 14:06:28 +01:00
|
|
|
"text/template"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2020-09-13 14:24:29 +01:00
|
|
|
aspellLang string = "en_GB"
|
2020-09-12 14:06:28 +01:00
|
|
|
defaultImageName string = "cv-builder"
|
|
|
|
defaultImageTag string = "latest"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ImageName generates the docker image name from the environment
|
|
|
|
// variables IMAGE_NAME and IMAGE_TAG. Default vaules will be used
|
|
|
|
// if these variables are not set or empty.
|
|
|
|
func ImageName() string {
|
|
|
|
name := os.Getenv("IMAGE_NAME")
|
|
|
|
if len(name) == 0 {
|
|
|
|
name = defaultImageName
|
|
|
|
}
|
|
|
|
|
|
|
|
tag := os.Getenv("IMAGE_TAG")
|
|
|
|
if len(tag) == 0 {
|
|
|
|
tag = defaultImageTag
|
|
|
|
}
|
|
|
|
|
|
|
|
return name + ":" + tag
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateCVTex generates the CV docuemnt as a Tex file.
|
|
|
|
func CreateCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName string) error {
|
|
|
|
fmt.Printf("INFO: Attempting to read data from %s...\n", cvJsonDataFile)
|
|
|
|
|
|
|
|
data, err := ioutil.ReadFile(cvJsonDataFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("ERROR: Unable to read data from file. %s\n", err.Error())
|
|
|
|
}
|
|
|
|
fmt.Println("INFO: Successfully read data.")
|
|
|
|
|
|
|
|
fmt.Println("INFO: Attempting to unmarshal JSON data...")
|
|
|
|
|
|
|
|
var cv Cv
|
|
|
|
if err = json.Unmarshal(data, &cv); err != nil {
|
|
|
|
return fmt.Errorf("ERROR: Unable to unmarshal JSON data. %s\n", err.Error())
|
|
|
|
}
|
|
|
|
fmt.Println("INFO: JSON unmarshalling was successful.")
|
|
|
|
|
|
|
|
// if CV_CONTACT_PHONE is set then add it to the CV
|
|
|
|
phone := os.Getenv("CV_CONTACT_PHONE")
|
|
|
|
if len(phone) > 0 {
|
|
|
|
cv.Contact.Phone = phone
|
|
|
|
}
|
|
|
|
|
|
|
|
cvOutputPath := cvOutputDir + "/" + cvOutputFileName
|
|
|
|
fmt.Printf("INFO: Attempting to create output file %s...\n", cvOutputPath)
|
|
|
|
|
|
|
|
if err = os.MkdirAll(cvOutputDir, 0750); err != nil {
|
|
|
|
return fmt.Errorf("ERROR: Unable to create output directory %s. %s\n", cvOutputDir, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
output, err := os.Create(cvOutputPath)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("ERROR: Unable to create output file %s. %s\n", cvOutputPath, err.Error())
|
|
|
|
}
|
|
|
|
fmt.Printf("INFO: Successfully created output file %s.\n", cvOutputPath)
|
|
|
|
defer output.Close()
|
|
|
|
|
|
|
|
fmt.Println("INFO: Attempting template execution...")
|
|
|
|
fmap := template.FuncMap{
|
|
|
|
"notLastElement": notLastElement,
|
|
|
|
"join": join,
|
|
|
|
"durationToString": durationToString,
|
|
|
|
}
|
|
|
|
|
|
|
|
t := template.Must(template.New("cv.tmpl.tex").Funcs(fmap).Delims("<<", ">>").ParseGlob(cvTemplateDir + "*.tmpl.tex"))
|
|
|
|
|
|
|
|
if err = t.Execute(output, cv); err != nil {
|
|
|
|
return fmt.Errorf("ERROR: Unable to execute the CV template. %s\n", err.Error())
|
|
|
|
}
|
|
|
|
fmt.Println("INFO: Template execution successful.")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2020-09-13 14:24:29 +01:00
|
|
|
|
|
|
|
func SpellCheck(dataFile, aspellPersonalWordlist string) error {
|
|
|
|
fmt.Printf("INFO: Reading data from %s...\n", dataFile)
|
|
|
|
|
|
|
|
data, err := ioutil.ReadFile(dataFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to read data from %s, %s", dataFile, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
// declare the aspell command and its standard input pipe.
|
|
|
|
cmd := exec.Command("aspell", "-d", aspellLang, "-p", aspellPersonalWordlist, "list")
|
|
|
|
stdin, err := cmd.StdinPipe()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// write the CV data to standard input for piping.
|
|
|
|
go func() {
|
|
|
|
defer stdin.Close()
|
|
|
|
io.WriteString(stdin, string(data))
|
|
|
|
}()
|
|
|
|
|
|
|
|
// run aspell and get the list of mispelt words (if any).
|
|
|
|
// (the output is a string.)
|
|
|
|
fmt.Println("Running aspell...")
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
list := strings.Split(string(out), "\n")
|
|
|
|
if list[len(list)-1] == "" {
|
|
|
|
list = list[:len(list)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(list) > 0 {
|
|
|
|
var b strings.Builder
|
|
|
|
errMsg := fmt.Sprintf("the following spelling errors were found in %s:", dataFile)
|
|
|
|
b.WriteString(errMsg)
|
|
|
|
|
|
|
|
for _, v := range list {
|
|
|
|
s := "\n- " + v
|
|
|
|
b.WriteString(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Errorf(b.String())
|
|
|
|
} else {
|
|
|
|
fmt.Println("No spelling errors were found.")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|