diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 47 |
1 files changed, 35 insertions, 12 deletions
@@ -5,6 +5,7 @@ import ( "encoding/json" "encoding/xml" "errors" + "flag" "fmt" "html/template" "io" @@ -57,6 +58,7 @@ type site struct { pages map[string][]*Page sources []source templates *template.Template + fallback string warnings []string } @@ -65,17 +67,30 @@ type manifest struct { } func main() { - if len(os.Args) != 2 { - fmt.Fprintln(os.Stderr, "usage: weft <site-root>") + flags := flag.NewFlagSet("weft", flag.ContinueOnError) + fallback := flags.String("fallback", "page", "fallback template for Markdown pages") + flags.Usage = func() { fmt.Fprintln(flags.Output(), "usage: weft [-fallback template] <site-root>") } + if err := flags.Parse(os.Args[1:]); err != nil { os.Exit(2) } - if err := build(os.Args[1]); err != nil { + if flags.NArg() != 1 { + flags.Usage() + os.Exit(2) + } + if err := buildWithFallback(flags.Arg(0), *fallback); err != nil { fmt.Fprintln(os.Stderr, "weft:", err) os.Exit(1) } } func build(root string) error { + return buildWithFallback(root, "page") +} + +func buildWithFallback(root, fallback string) error { + if strings.TrimSpace(fallback) == "" { + return errors.New("fallback template cannot be empty") + } abs, err := filepath.Abs(root) if err != nil { return err @@ -88,7 +103,7 @@ func build(root string) error { return fmt.Errorf("site root is not a directory: %s", abs) } - s := &site{root: abs, pages: map[string][]*Page{}} + s := &site{root: abs, fallback: fallback, pages: map[string][]*Page{}} if err := s.discover(); err != nil { return err } @@ -367,6 +382,7 @@ func relativePath(from, target string) string { if strings.HasPrefix(target, "http://") || strings.HasPrefix(target, "https://") || strings.HasPrefix(target, "mailto:") || strings.HasPrefix(target, "#") { return target } + directory := strings.HasSuffix(target, "/") fromDir := path.Dir(strings.TrimPrefix(from, "/")) if fromDir == "." { fromDir = "" @@ -376,7 +392,11 @@ func relativePath(from, target string) string { if err != nil { return target } - return filepath.ToSlash(rel) + rel = filepath.ToSlash(rel) + if directory { + return strings.TrimSuffix(rel, "/") + "/" + } + return rel } func sortPages(pages []*Page, key string) []*Page { @@ -462,13 +482,7 @@ func (s *site) render() (map[string][]byte, error) { name := src.path if src.kind == "markdown" { current = src.page - name = "page" - if src.output == "weblog" || strings.HasPrefix(src.output, "weblog/") { - name = "weblog" - } - if src.output == "notes" || strings.HasPrefix(src.output, "notes/") { - name = "note" - } + name = s.markdownTemplate(src.path) } else { current = &Page{SourcePath: src.path, OutputPath: src.output, URL: "/" + src.output, CanonicalURL: "https://tjp.lol/" + src.output, Meta: map[string]any{}} } @@ -484,6 +498,15 @@ func (s *site) render() (map[string][]byte, error) { return outputs, nil } +func (s *site) markdownTemplate(sourcePath string) string { + for candidate := strings.TrimSuffix(sourcePath, ".md"); candidate != "." && candidate != ""; candidate = path.Dir(candidate) { + if s.templates.Lookup(candidate) != nil { + return candidate + } + } + return s.fallback +} + func (s *site) validate(outputs map[string][]byte) error { tracked, err := s.readManifest() if err != nil { |
