cdn/main.go

119 lines
2.6 KiB
Go
Raw Normal View History

package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"runtime"
"time"
"golang.org/x/sync/errgroup"
)
var (
ctx = context.Background()
previewPort = "8080"
// Specify the starting directory, for consistency
_, f, _, _ = runtime.Caller(0)
)
// genListingPages generates listing pages recursively inside provided directory
func genListingPages(path string) error {
entries, err := os.ReadDir(path)
if err != nil {
return err
}
indexFile, err := os.Create(filepath.Join(path, "index.html"))
if err != nil {
return err
}
if err := listingPage(path, entries).Render(ctx, indexFile); err != nil {
return err
}
// Goroutines are cheap, so just spawn them needlessly \^-^/
errGroup := new(errgroup.Group)
for _, entry := range entries {
entry := entry
if entry.IsDir() {
errGroup.Go(func() error {
return genListingPages(filepath.Join(path, entry.Name()))
})
}
}
return errGroup.Wait()
}
// preview Previews the website at specified root directory on localhost:<port>
func preview(root, port string) error {
http.Handle("/", http.FileServer(
http.Dir(
filepath.Join(filepath.Dir(f), root),
),
))
fmt.Println("Serving the preview webpage at http://localhost:" + port)
srv := &http.Server{
Addr: ":" + port,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
return srv.ListenAndServe()
}
// generate generates index.html files for the root directory
func generate(root string) error {
// NOTE: it also generate one for the root directory. We'll override this file later
if err := genListingPages(root); err != nil {
return err
}
// Render the home page to override the written listing page at root
homePage, err := os.Create(filepath.Join(root, "index.html"))
if err != nil {
return err
}
return indexPage().Render(ctx, homePage)
}
func main() {
genFlag := flag.Bool("gen", false, "Generate index files")
previewFlag := flag.Bool("preview", false, "Preview the built website")
flag.Usage = func() {
fmt.Printf(`Usage: go run *.go [OPTIONS] DIR
Arguments:
DIR
Path to the directory containing the source files
Options:
`)
flag.PrintDefaults()
}
flag.Parse()
// The root directory argument is required
if len(flag.Args()) != 1 {
log.Fatal("[ERROR] exactly 1 argument DIR is required")
}
rootDir := flag.Arg(0)
if *genFlag {
if err := generate(rootDir); err != nil {
log.Fatalf("[ERROR] %v", err)
}
}
// Only preview after things are generated
if *previewFlag {
if err := preview(rootDir, previewPort); err != nil {
log.Fatalf("[ERROR] %v", err)
}
}
}