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  }