package staticgen import ( "io/ioutil" "log" "net/http" "os" "os/exec" "path/filepath" "strings" fb "github.com/filebrowser/filebrowser" ) // Jekyll is the Jekyll static website generator. type Jekyll struct { // Website root Root string `name:"Website Root"` // Public folder Public string `name:"Public Directory"` // Jekyll executable path Exe string `name:"Executable"` // Jekyll arguments Args []string `name:"Arguments"` // Indicates if we should clean public before a new publish. CleanPublic bool `name:"Clean Public"` // previewPath is the temporary path for a preview previewPath string } // Name is the plugin's name. func (j Jekyll) Name() string { return "jekyll" } // SettingsPath retrieves the correct settings path. func (j Jekyll) SettingsPath() string { return "/_config.yml" } // Hook is the pre-api handler. func (j Jekyll) Hook(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { return 0, nil } // Publish publishes a post. func (j Jekyll) Publish(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { filename := filepath.Join(c.User.Scope, r.URL.Path) // We only run undraft command if it is a file. if err := j.undraft(filename); err != nil { return http.StatusInternalServerError, err } // Regenerates the file j.run() return 0, nil } // Preview handles the preview path. func (j *Jekyll) Preview(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { // Get a new temporary path if there is none. if j.previewPath == "" { path, err := ioutil.TempDir("", "") if err != nil { return http.StatusInternalServerError, err } j.previewPath = path } // Build the arguments to execute Hugo: change the base URL, // build the drafts and update the destination. args := j.Args args = append(args, "--baseurl", c.RootURL()+"/preview/") args = append(args, "--drafts") args = append(args, "--destination", j.previewPath) // Builds the preview. if err := runCommand(j.Exe, args, j.Root); err != nil { return http.StatusInternalServerError, err } // Serves the temporary path with the preview. http.FileServer(http.Dir(j.previewPath)).ServeHTTP(w, r) return 0, nil } func (j Jekyll) run() { // If the CleanPublic option is enabled, clean it. if j.CleanPublic { os.RemoveAll(j.Public) } if err := runCommand(j.Exe, j.Args, j.Root); err != nil { log.Println(err) } } func (j Jekyll) undraft(file string) error { if !strings.Contains(file, "_drafts") { return nil } return os.Rename(file, strings.Replace(file, "_drafts", "_posts", 1)) } // Setup sets up the plugin. func (j *Jekyll) Setup() error { var err error if j.Exe, err = exec.LookPath("jekyll"); err != nil { return err } if len(j.Args) == 0 { j.Args = []string{"build"} } if j.Args[0] != "build" { j.Args = append([]string{"build"}, j.Args...) } return nil }