Generate an index of the recipes

This commit is contained in:
Miguel de la Cruz 2024-07-06 06:23:32 +02:00
parent 482859f212
commit 055358f2db
5 changed files with 42 additions and 3 deletions

View file

@ -11,7 +11,7 @@ A simple CLI tool to generate a static website from a
- [ ] Improve the steps rendering logic to avoid doing all of it - [ ] Improve the steps rendering logic to avoid doing all of it
inside a template function. inside a template function.
- [X] Add image support for steps and the recipe. - [X] Add image support for steps and the recipe.
- [ ] Add an `index.html` file that lists all the recipes. - [X] Add an `index.html` file that lists all the recipes.
- [X] Embed the default `style.css` file. - [X] Embed the default `style.css` file.
- [ ] Add command to copy the embedded templates to an external - [ ] Add command to copy the embedded templates to an external
directory. directory.

1
cmd.go
View file

@ -4,6 +4,7 @@ type generateCmd struct {
Path string `arg:"" help:"Path to the directory with the recipes."` Path string `arg:"" help:"Path to the directory with the recipes."`
Output string `default:"dist" help:"Path to the directory where the files will be generated."` Output string `default:"dist" help:"Path to the directory where the files will be generated."`
NameKey string `default:"name" short:"n" help:"The metadata key for the recipe name."` NameKey string `default:"name" short:"n" help:"The metadata key for the recipe name."`
Title string `default:"Recipes directory" short:"t" help:"The title to use at the recipe index."`
} }
var cli struct { var cli struct {

View file

@ -27,6 +27,11 @@ const (
timerSuffix = "</span>" timerSuffix = "</span>"
) )
type RecipeFile struct {
Name string
Path string
}
//go:embed templates //go:embed templates
var embedTmpl embed.FS var embedTmpl embed.FS
var imageExtensions = []string{".jpg", ".jpeg", ".png"} var imageExtensions = []string{".jpg", ".jpeg", ".png"}
@ -191,6 +196,7 @@ func (g *generateCmd) Run() error {
return fmt.Errorf("cannot create directory on path %q: %w", g.Output, err) return fmt.Errorf("cannot create directory on path %q: %w", g.Output, err)
} }
recipeFiles := []*RecipeFile{}
walkErr := filepath.WalkDir(g.Path, func(path string, d fs.DirEntry, err error) error { walkErr := filepath.WalkDir(g.Path, func(path string, d fs.DirEntry, err error) error {
slog.Debug("Walking through file", "path", path) slog.Debug("Walking through file", "path", path)
@ -248,7 +254,9 @@ func (g *generateCmd) Run() error {
recipeName = name recipeName = name
} }
recipeDistPath := filepath.Join(g.Output, filepath.Dir(relpath), fmt.Sprintf("%s.html", filenameWithoutExt)) htmlPath := filepath.Join(filepath.Dir(relpath), fmt.Sprintf("%s.html", filenameWithoutExt))
recipeFiles = append(recipeFiles, &RecipeFile{Name: recipeName, Path: htmlPath})
recipeDistPath := filepath.Join(g.Output, htmlPath)
data := map[string]any{"name": recipeName, "recipe": recipe, "path": path, "relpath": getRelpath(relpath)} data := map[string]any{"name": recipeName, "recipe": recipe, "path": path, "relpath": getRelpath(relpath)}
slog.Debug("Executing template", "recipeName", recipeName, "recipeWebPath", recipeDistPath) slog.Debug("Executing template", "recipeName", recipeName, "recipeWebPath", recipeDistPath)
if err := executeTemplateToFile("recipe", data, recipeDistPath); err != nil { if err := executeTemplateToFile("recipe", data, recipeDistPath); err != nil {
@ -261,6 +269,7 @@ func (g *generateCmd) Run() error {
return fmt.Errorf("error while walking directory %q: %w", g.Path, walkErr) return fmt.Errorf("error while walking directory %q: %w", g.Path, walkErr)
} }
// copy styles
styleFile, err := embedTmpl.Open(filepath.Join("templates", "style.css")) styleFile, err := embedTmpl.Open(filepath.Join("templates", "style.css"))
if err != nil { if err != nil {
return fmt.Errorf("cannot read style.css embed file: %w", err) return fmt.Errorf("cannot read style.css embed file: %w", err)
@ -270,5 +279,13 @@ func (g *generateCmd) Run() error {
return fmt.Errorf("cannot copy style.css: %w", err) return fmt.Errorf("cannot copy style.css: %w", err)
} }
// generate index
data := map[string]any{"title": g.Title, "recipes": recipeFiles}
indexpath := filepath.Join(g.Output, "index.html")
slog.Debug("Executing index template", "title", g.Title, "recipes", len(recipeFiles), "indexpath", indexpath)
if err := executeTemplateToFile("index", data, indexpath); err != nil {
return fmt.Errorf("cannot execute template \"index\" to file %q: %w", indexpath, err)
}
return nil return nil
} }

21
templates/index.html.tmpl Normal file
View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{.title}}</title>
<link rel="icon" type="image/png" href="{{.relpath}}favicon.png" />
<link rel="stylesheet" type="text/css" href="{{.relpath}}style.css" />
</head>
<body>
<h1>{{.title}}</h1>
{{if ne (len .recipes) 0}}
<ul>
{{range .recipes}}
<li><a href="{{.Path}}">{{.Name}}</a></li>
{{end}}
</ul>
{{end}}
</body>
</html>

View file

@ -10,7 +10,7 @@ body {
.cookware { .cookware {
font-weight: bold; font-weight: bold;
color: red; color: brown;
} }
.timer { .timer {