commit 9e7950ddbafd50841f34c87dd5139e916333652c Author: Leon Mika Date: Sun Feb 1 15:00:26 2026 +1100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..92cd4c2 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# projdoc - Project Documentation Generator + +A Go package used for generating HTML documentation for Go projects. Modelled after 11ty. + +To learn more, visit the [more](/more). \ No newline at end of file diff --git a/_site/more.md b/_site/more.md new file mode 100644 index 0000000..4c395c5 --- /dev/null +++ b/_site/more.md @@ -0,0 +1,3 @@ +# More + +This is more information about this project and it's good. \ No newline at end of file diff --git a/cmd/doc/main.go b/cmd/doc/main.go new file mode 100644 index 0000000..91f55f5 --- /dev/null +++ b/cmd/doc/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "log" + + "lmika.dev/pkg/progdoc" +) + +func main() { + if err := progdoc.Site().Build(); err != nil { + log.Fatal(err) + } +} diff --git a/generator.go b/generator.go new file mode 100644 index 0000000..a72d979 --- /dev/null +++ b/generator.go @@ -0,0 +1,42 @@ +package progdoc + +import ( + "os" + "path/filepath" +) + +type generator struct { + outDir string +} + +func (g generator) genSite(siteMap siteMap) (err error) { + outDir := g.outDir + if outDir == "" { + outDir, err = os.MkdirTemp("", "") + if err != nil { + return err + } + } + + for _, page := range siteMap.Pages { + srcCtx := SourceCtx{Meta: siteMap.Meta} + + targetPathDir := filepath.Join(g.outDir, page.Target) + err := os.MkdirAll(targetPathDir, os.ModePerm) + if err != nil { + return err + } + + if err := (func(fileName string) error { + f, err := os.Create(fileName) + if err != nil { + return err + } + defer f.Close() + return page.Source.HTML(f, &srcCtx) + })(filepath.Join(targetPathDir, "index.html")); err != nil { + return err + } + } + return nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4f3d309 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module lmika.dev/pkg/progdoc + +go 1.24.3 + +require github.com/yuin/goldmark v1.7.16 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..63cb70d --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= +github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= diff --git a/mdsource.go b/mdsource.go new file mode 100644 index 0000000..7dc937a --- /dev/null +++ b/mdsource.go @@ -0,0 +1,34 @@ +package progdoc + +import ( + "io" + "os" + + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/extension" + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/renderer/html" +) + +type mdSource struct { + MDFile string +} + +func (m mdSource) HTML(w io.Writer, srcCtx *SourceCtx) error { + srcBytes, err := os.ReadFile(m.MDFile) + if err != nil { + return err + } + + md := goldmark.New( + goldmark.WithExtensions(extension.GFM), + goldmark.WithParserOptions( + parser.WithAutoHeadingID(), + ), + goldmark.WithRendererOptions( + html.WithUnsafe(), + ), + ) + + return md.Convert(srcBytes, w) +} diff --git a/models.go b/models.go new file mode 100644 index 0000000..973e54c --- /dev/null +++ b/models.go @@ -0,0 +1,25 @@ +package progdoc + +import "io" + +type pageSource interface { + HTML(w io.Writer, srcCtx *SourceCtx) error +} + +type siteMeta struct { + Title string +} + +type sitePage struct { + Target string + Source pageSource +} + +type siteMap struct { + Meta *siteMeta + Pages []sitePage +} + +type SourceCtx struct { + Meta *siteMeta +} diff --git a/progdoc.go b/progdoc.go new file mode 100644 index 0000000..ce873b4 --- /dev/null +++ b/progdoc.go @@ -0,0 +1,26 @@ +package progdoc + +type SiteBuilder struct { +} + +func Site() *SiteBuilder { + return &SiteBuilder{} +} + +func (sb *SiteBuilder) Build() 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"}}}, + }, + } + + gen := generator{outDir: "out"} + if err := gen.genSite(siteMap); err != nil { + return err + } + return nil +} diff --git a/stdlayout.go b/stdlayout.go new file mode 100644 index 0000000..a5b5822 --- /dev/null +++ b/stdlayout.go @@ -0,0 +1,44 @@ +package progdoc + +import ( + "bytes" + "html/template" + "io" +) + +type stdLayoutSource struct { + MainSource pageSource +} + +func (s stdLayoutSource) HTML(w io.Writer, srcCtx *SourceCtx) error { + var data struct { + Meta *siteMeta + Content template.HTML + } + + var content bytes.Buffer + if err := s.MainSource.HTML(&content, srcCtx); err != nil { + return err + } + + data.Meta = srcCtx.Meta + data.Content = template.HTML(content.String()) + + return stdLayoutTemplate.Execute(w, data) +} + +var stdLayoutTemplate = template.Must(template.New("stdlayout").Parse(` + + + + + {{.Meta.Title}} + + + +
+ {{.Content}} +
+ + +`))