2021-11-30 15:17:09 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-12-25 18:52:03 +00:00
|
|
|
"context"
|
2022-12-30 09:41:19 +00:00
|
|
|
"fmt"
|
2021-11-30 15:17:09 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2022-07-11 04:26:24 +00:00
|
|
|
"text/template"
|
2021-11-30 15:17:09 +00:00
|
|
|
|
2023-10-12 04:02:06 +00:00
|
|
|
"github.com/google/go-github/v56/github"
|
2023-08-15 08:27:59 +00:00
|
|
|
"golang.org/x/oauth2"
|
2022-12-30 09:41:19 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2023-08-15 09:41:35 +00:00
|
|
|
|
|
|
|
"github.com/make-go-great/netrc-go"
|
2021-11-30 15:17:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-07-11 04:26:24 +00:00
|
|
|
postFilesPath = "posts"
|
|
|
|
templatePostPath = "templates/post.html"
|
|
|
|
|
2022-07-10 11:09:42 +00:00
|
|
|
generatedPath = "docs"
|
2022-07-11 04:26:24 +00:00
|
|
|
|
|
|
|
extHTML = ".html"
|
2023-08-15 09:41:35 +00:00
|
|
|
|
|
|
|
netrcPath = "~/.netrc"
|
|
|
|
netrcMachineGitHub = "github.com"
|
2021-11-30 15:17:09 +00:00
|
|
|
)
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
type templatePostData struct {
|
2022-12-30 10:08:50 +00:00
|
|
|
Index string
|
|
|
|
Body string
|
2022-07-11 04:26:24 +00:00
|
|
|
}
|
|
|
|
|
2021-11-30 15:17:09 +00:00
|
|
|
func main() {
|
2022-12-25 18:52:03 +00:00
|
|
|
ctx := context.Background()
|
|
|
|
|
2022-07-10 11:32:01 +00:00
|
|
|
// Cleanup generated path
|
|
|
|
if err := os.RemoveAll(generatedPath); err != nil {
|
|
|
|
log.Fatalln("Failed to remove all", generatedPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(generatedPath, 0o777); err != nil {
|
|
|
|
log.Fatalln("Failed to mkdir all", generatedPath)
|
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Read post files directory
|
|
|
|
postFiles, err := os.ReadDir(postFilesPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
if err != nil {
|
2022-07-11 04:26:24 +00:00
|
|
|
log.Fatalln("Failed to read dir", postFilesPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Prepare template
|
|
|
|
templatePostBytes, err := os.ReadFile(templatePostPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
if err != nil {
|
2022-07-11 04:26:24 +00:00
|
|
|
log.Fatalln("Failed to read file", templatePostPath, err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
templatePost, err := template.New("post").Parse(string(templatePostBytes))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to parse template", err)
|
|
|
|
}
|
|
|
|
|
2022-12-25 18:52:03 +00:00
|
|
|
// Prepare GitHub
|
2023-08-15 09:41:35 +00:00
|
|
|
netrcData, err := netrc.ParseFile(netrcPath)
|
2023-08-15 08:27:59 +00:00
|
|
|
if err != nil {
|
2023-08-15 09:41:35 +00:00
|
|
|
log.Fatalln("Failed to read file netrc", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var ghAccessToken string
|
|
|
|
for _, machine := range netrcData.Machines {
|
|
|
|
if machine.Name == netrcMachineGitHub {
|
|
|
|
ghAccessToken = machine.Password
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ghAccessToken == "" {
|
|
|
|
log.Fatalln("Empty GitHub token in netrc")
|
2023-08-15 08:27:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ghTokenSrc := oauth2.StaticTokenSource(
|
|
|
|
&oauth2.Token{
|
2023-08-15 09:41:35 +00:00
|
|
|
AccessToken: strings.TrimSpace(ghAccessToken),
|
2023-08-15 08:27:59 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
ghHTTPClient := oauth2.NewClient(ctx, ghTokenSrc)
|
|
|
|
ghClient := github.NewClient(ghHTTPClient)
|
2022-07-11 04:26:24 +00:00
|
|
|
|
2022-12-30 09:41:19 +00:00
|
|
|
eg := new(errgroup.Group)
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Generate post files
|
|
|
|
for _, postFile := range postFiles {
|
|
|
|
if postFile.IsDir() {
|
2021-11-30 15:17:09 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-12-30 09:41:19 +00:00
|
|
|
postFilename := postFile.Name()
|
|
|
|
|
|
|
|
eg.Go(func() error {
|
|
|
|
// Prepare post file
|
|
|
|
mdFilename := filepath.Join(postFilesPath, postFilename)
|
|
|
|
mdFileBytes, err := os.ReadFile(mdFilename)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("os: failed to read file %s: %w", mdFilename, err)
|
|
|
|
}
|
|
|
|
|
2023-10-12 04:02:06 +00:00
|
|
|
ghMarkdown, _, err := ghClient.Markdown.Render(ctx, string(mdFileBytes), nil)
|
2022-12-30 09:41:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("github: failed to markdown: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare html file
|
|
|
|
htmlFilename := strings.TrimSuffix(postFilename, filepath.Ext(postFilename)) + extHTML
|
|
|
|
htmlFilepath := filepath.Join(generatedPath, htmlFilename)
|
|
|
|
|
|
|
|
htmlFile, err := os.OpenFile(htmlFilepath, os.O_RDWR|os.O_CREATE, 0o600)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("os: failed to open file %s: %w", htmlFilepath, err)
|
|
|
|
}
|
|
|
|
defer htmlFile.Close()
|
|
|
|
|
2022-12-30 10:08:50 +00:00
|
|
|
// Ignore index in index file
|
2023-08-09 07:22:58 +00:00
|
|
|
indexHTML := `<h2><a href="index.html"><code>~</code></a></h2>`
|
2022-12-30 10:08:50 +00:00
|
|
|
if strings.Contains(postFilename, "index") {
|
|
|
|
indexHTML = ""
|
|
|
|
}
|
|
|
|
|
2022-12-30 09:41:19 +00:00
|
|
|
if err := templatePost.Execute(htmlFile, templatePostData{
|
2022-12-30 10:08:50 +00:00
|
|
|
Index: indexHTML,
|
|
|
|
Body: ghMarkdown,
|
2022-12-30 09:41:19 +00:00
|
|
|
}); err != nil {
|
|
|
|
return fmt.Errorf("template: failed to execute: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2022-12-25 18:52:03 +00:00
|
|
|
})
|
2022-07-11 04:26:24 +00:00
|
|
|
|
2022-12-30 09:41:19 +00:00
|
|
|
}
|
2021-11-30 15:17:09 +00:00
|
|
|
|
2022-12-30 09:41:19 +00:00
|
|
|
// Wait for all HTTP fetches to complete.
|
|
|
|
if err := eg.Wait(); err != nil {
|
|
|
|
log.Fatalln("I am sorry :(", err)
|
|
|
|
} else {
|
|
|
|
log.Println("Build successfully. Are you happy now?")
|
2022-07-11 04:26:24 +00:00
|
|
|
}
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|