From 64e19d8700cec39436e573a277f1f5f376a19bf5 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sun, 1 Feb 2026 17:04:15 +1100 Subject: [PATCH] Added options to configure the site --- _site/another.md | 2 ++ cmd/doc/main.go | 6 +++- generator.go | 2 +- models.go | 8 ++--- progdoc.go | 25 ++++++++------ siteopts.go | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ stdlayout.go | 2 +- 7 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 _site/another.md create mode 100644 siteopts.go diff --git a/_site/another.md b/_site/another.md new file mode 100644 index 0000000..ccc8acd --- /dev/null +++ b/_site/another.md @@ -0,0 +1,2 @@ +This is some more content. + diff --git a/cmd/doc/main.go b/cmd/doc/main.go index 5bf459d..9f3e9c2 100644 --- a/cmd/doc/main.go +++ b/cmd/doc/main.go @@ -7,7 +7,11 @@ import ( ) func main() { - if err := progdoc.Site().Publish(); err != nil { + if err := progdoc.Site( + progdoc.Meta(progdoc.SiteMeta{Title: "Prog Doc"}), + progdoc.SourceFile("/", "README.md"), + progdoc.SourceDir("/", "_site"), + ).Publish(); err != nil { log.Fatal(err) } } diff --git a/generator.go b/generator.go index bd9ac7a..6b27813 100644 --- a/generator.go +++ b/generator.go @@ -25,7 +25,7 @@ func (g generator) genSite(siteMap siteMap) (_ generation, err error) { for _, page := range siteMap.Pages { srcCtx := SourceCtx{Meta: siteMap.Meta} - targetPathDir := filepath.Join(g.outDir, page.Target) + targetPathDir := filepath.Join(outDir, page.Path) err := os.MkdirAll(targetPathDir, os.ModePerm) if err != nil { return generation{}, err diff --git a/models.go b/models.go index 973e54c..c099477 100644 --- a/models.go +++ b/models.go @@ -6,20 +6,20 @@ type pageSource interface { HTML(w io.Writer, srcCtx *SourceCtx) error } -type siteMeta struct { +type SiteMeta struct { Title string } type sitePage struct { - Target string + Path string Source pageSource } type siteMap struct { - Meta *siteMeta + Meta *SiteMeta Pages []sitePage } type SourceCtx struct { - Meta *siteMeta + Meta *SiteMeta } diff --git a/progdoc.go b/progdoc.go index 902f5d9..6d5e4b3 100644 --- a/progdoc.go +++ b/progdoc.go @@ -12,21 +12,26 @@ import ( ) type SiteBuilder struct { + opts []Option } -func Site() *SiteBuilder { - return &SiteBuilder{} +func Site(opts ...Option) *SiteBuilder { + return &SiteBuilder{ + opts: opts, + } } func (sb *SiteBuilder) Publish() error { - siteMap := siteMap{ - Meta: &siteMeta{ - Title: "Prog Doc", - }, - Pages: []sitePage{ - {Target: "/", Source: stdLayoutSource{MainSource: mdSource{MDFile: "README.md"}}}, - {Target: "/more", Source: stdLayoutSource{MainSource: mdSource{MDFile: "_site/more.md"}}}, - }, + siteMap := siteMap{} + + for _, opt := range sb.opts { + if err := opt.configSitemap(&siteMap); err != nil { + return err + } + } + + if len(siteMap.Pages) == 0 { + return errors.New("No pages found") } gen := generator{} diff --git a/siteopts.go b/siteopts.go new file mode 100644 index 0000000..249ca0e --- /dev/null +++ b/siteopts.go @@ -0,0 +1,90 @@ +package progdoc + +import ( + "errors" + "log" + "os" + "path/filepath" + "strings" +) + +type Option struct { + configSitemap func(sm *siteMap) error +} + +func Meta(meta SiteMeta) Option { + return Option{ + configSitemap: func(sm *siteMap) error { + sm.Meta = &meta + return nil + }, + } +} + +func SourceFile(path, file string) Option { + return Option{ + configSitemap: func(sm *siteMap) error { + _, err := os.Stat(file) + if err != nil { + return err + } + + // TODO: support things other than markdown + src, err := inferSourceFromFilename(file) + if err != nil { + return err + } + + log.Printf("Page '%s' -> %s", path, file) + sm.Pages = append(sm.Pages, sitePage{ + Path: path, + Source: stdLayoutSource{MainSource: src}, + }) + + return nil + }, + } +} + +func SourceDir(basePath, dir string) Option { + return Option{ + configSitemap: func(sm *siteMap) error { + return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && info.Mode().IsRegular() { + src, err := inferSourceFromFilename(path) + if err != nil { + return nil + } + + relPath, err := filepath.Rel(dir, strings.TrimSuffix(path, filepath.Ext(path))) + if err != nil { + return nil + } + targetPath := filepath.Join(basePath, relPath) + + log.Printf("Page '%s' -> %s", targetPath, path) + sm.Pages = append(sm.Pages, sitePage{ + Path: relPath, + Source: stdLayoutSource{MainSource: src}, + }) + } + return nil + }) + }, + } +} + +func inferSourceFromFilename(fname string) (pageSource, error) { + absName, err := filepath.Abs(fname) + if err != nil { + return nil, err + } + + if strings.HasSuffix(absName, ".md") { + return mdSource{MDFile: absName}, nil + } + return nil, errors.New("unsupported file type") +} diff --git a/stdlayout.go b/stdlayout.go index a5b5822..e2f3190 100644 --- a/stdlayout.go +++ b/stdlayout.go @@ -12,7 +12,7 @@ type stdLayoutSource struct { func (s stdLayoutSource) HTML(w io.Writer, srcCtx *SourceCtx) error { var data struct { - Meta *siteMeta + Meta *SiteMeta Content template.HTML }