github.com/exercism/configlet@v3.9.3-0.20200318193232-c70be6269e71+incompatible/track/exercise_readme.go (about) 1 package track 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "text/template" 9 ) 10 11 const ( 12 dirExercises = "exercises" 13 filenameReadme = "README.md" 14 ) 15 16 var ( 17 pathTrackTemplate = filepath.Join("config", "exercise_readme.go.tmpl") 18 pathTrackInsert = filepath.Join("config", "exercise-readme-insert.md") 19 pathTrackInsertDeprecated = filepath.Join("docs", "EXERCISE_README_INSERT.md") 20 pathExerciseTemplate = filepath.Join(".meta", "readme.go.tmpl") 21 pathExerciseInsert = filepath.Join(".meta", "hints.md") 22 pathExerciseInsertDeprecated = "HINTS.md" 23 ) 24 25 // ExerciseReadme contains the data necessary to generate a README 26 // for an Exercism exercise. 27 type ExerciseReadme struct { 28 Spec *ProblemSpecification 29 Hints string 30 TrackInsert string 31 template string 32 trackDir string 33 dir string 34 } 35 36 // NewExerciseReadme locates and reads all the data to create an ExerciseReadme. 37 func NewExerciseReadme(root, trackID, slug string) (ExerciseReadme, error) { 38 readme := ExerciseReadme{ 39 trackDir: filepath.Join(root, trackID), 40 dir: filepath.Join(root, trackID, dirExercises, slug), 41 } 42 43 spec, err := NewProblemSpecification(root, trackID, slug) 44 if err != nil { 45 return readme, err 46 } 47 readme.Spec = spec 48 49 if err := readme.readTemplate(); err != nil { 50 return readme, err 51 } 52 53 if err := readme.readHints(); err != nil { 54 return readme, err 55 } 56 57 if err := readme.readTrackInsert(); err != nil { 58 return readme, err 59 } 60 61 return readme, nil 62 } 63 64 // Generate produces a README from the template and data. 65 func (readme ExerciseReadme) Generate() (string, error) { 66 t, err := template.New("readme").Parse(readme.template) 67 if err != nil { 68 return "", err 69 } 70 71 var bb bytes.Buffer 72 err = t.Execute(&bb, readme) 73 return bb.String(), err 74 } 75 76 // Write generates and writes the README to a file. 77 func (readme ExerciseReadme) Write() error { 78 s, err := readme.Generate() 79 if err != nil { 80 return err 81 } 82 return ioutil.WriteFile(filepath.Join(readme.dir, filenameReadme), []byte(s), 0644) 83 } 84 85 func (readme *ExerciseReadme) readTrackInsert() error { 86 b, err := ioutil.ReadFile(filepath.Join(readme.trackDir, pathTrackInsert)) 87 if err == nil { 88 readme.TrackInsert = string(b) 89 return nil 90 } 91 if !os.IsNotExist(err) { 92 return err 93 } 94 b, err = ioutil.ReadFile(filepath.Join(readme.trackDir, pathTrackInsertDeprecated)) 95 if err != nil && !os.IsNotExist(err) { 96 return err 97 } 98 readme.TrackInsert = string(b) 99 return nil 100 } 101 102 func (readme *ExerciseReadme) readHints() error { 103 b, err := ioutil.ReadFile(filepath.Join(readme.dir, pathExerciseInsert)) 104 if err == nil { 105 readme.Hints = string(b) 106 return nil 107 } 108 if !os.IsNotExist(err) { 109 return err 110 } 111 b, err = ioutil.ReadFile(filepath.Join(readme.dir, pathExerciseInsertDeprecated)) 112 if err != nil && !os.IsNotExist(err) { 113 return err 114 } 115 readme.Hints = string(b) 116 return nil 117 } 118 119 func (readme *ExerciseReadme) readTemplate() error { 120 b, err := ioutil.ReadFile(filepath.Join(readme.dir, pathExerciseTemplate)) 121 if err == nil { 122 readme.template = string(b) 123 return nil 124 } 125 if !os.IsNotExist(err) { 126 return err 127 } 128 129 b, err = ioutil.ReadFile(filepath.Join(readme.trackDir, pathTrackTemplate)) 130 if err != nil { 131 return err 132 } 133 readme.template = string(b) 134 return nil 135 }