Files
summercms/cmd/summer/docs.go
Jakub Zych dc6a03c714 feat(11.1-01): verify src= code blocks and add summer docs:sync
- src= fences name a file, a Go declaration or Example body, or a docs:start region
- confinement: relative clean paths inside the root, no dotfiles or .env,
  no nested go.mod modules, Examples need // Output:, test regions must run
- a drifted or missing snippet is a problem, so docs:build writes nothing
- docs:sync rewrites drifted fence bodies in place
- fences render in figure.code with a source caption; .md fences keep only the language
- bonfire ExampleCall is the first verified example, shown in setup/installation
2026-09-30 21:26:52 +02:00

92 lines
2.8 KiB
Go

package main
import (
"context"
"errors"
"git.golem15.com/golem15/summercms/internal/docsite"
"git.golem15.com/golem15/summercms/modules/bonfire"
)
func docsBuildCommand() bonfire.Command {
return bonfire.Command{
Name: "docs:build",
Description: "Build the documentation site",
Flags: []bonfire.Flag{
{Name: "root", Description: "Repository root; src= paths and modules/ resolve against it", Default: "."},
{Name: "src", Description: "Docs source directory (default <root>/docs)"},
{Name: "out", Description: "Output directory (default <root>/site)"},
{Name: "base-url", Description: "Base URL for site links (overrides site.yaml base_url)"},
{Name: "check", Description: "Validate the docs and write nothing", Bare: true},
},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
opts := docsOptions(in)
if flagTrue(in, "check") {
problems, err := docsite.Check(opts)
if err != nil {
return err
}
if len(problems) > 0 {
return reportDocsProblems(out, "docs:build", problems)
}
out.Printf("docs:build: no problems found\n")
return nil
}
result, problems, err := docsite.Build(opts)
if err != nil {
return err
}
if len(problems) > 0 {
return reportDocsProblems(out, "docs:build", problems)
}
out.Printf("docs:build: wrote %d pages to %s\n", result.Pages, result.Out)
return nil
},
}
}
func docsSyncCommand() bonfire.Command {
return bonfire.Command{
Name: "docs:sync",
Description: "Rewrite src= code blocks from their sources",
Flags: []bonfire.Flag{
{Name: "root", Description: "Repository root; src= paths resolve against it", Default: "."},
{Name: "src", Description: "Docs source directory (default <root>/docs)"},
},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
result, problems, err := docsite.Sync(docsOptions(in))
if err != nil {
return err
}
if len(problems) > 0 {
return reportDocsProblems(out, "docs:sync", problems)
}
if result.Snippets == 0 {
out.Printf("docs:sync: all snippets up to date\n")
return nil
}
out.Printf("docs:sync: updated %d snippets in %d files\n", result.Snippets, result.Files)
return nil
},
}
}
func docsOptions(in bonfire.Input) docsite.Options {
var opts docsite.Options
opts.Root, _ = in.Flag("root")
opts.Src, _ = in.Flag("src")
opts.Out, _ = in.Flag("out")
opts.BaseURL, _ = in.Flag("base-url")
return opts
}
// reportDocsProblems prints one line per problem and a summary, and returns
// a short error so the binary exits 1.
func reportDocsProblems(out bonfire.Output, cmd string, problems []docsite.Problem) error {
for _, p := range problems {
out.Printf("%s\n", p)
}
out.Printf("%s: %d problems, nothing written\n", cmd, len(problems))
return errors.New(cmd + " failed")
}