1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-30 09:59:03 +01:00
gojekyll/commands/commands.go
2017-07-19 16:06:43 -04:00

174 lines
4.0 KiB
Go

package commands
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"
yaml "gopkg.in/yaml.v2"
"github.com/montanaflynn/stats"
"github.com/osteele/gojekyll/pages"
"github.com/osteele/gojekyll/server"
"github.com/osteele/gojekyll/site"
"github.com/osteele/gojekyll/utils"
"github.com/osteele/liquid"
)
// main sets this
var commandStartTime = time.Now()
func buildCommand(site *site.Site) error {
watch := site.Config().Watch
logger.path("Destination:", site.DestDir())
logger.label("Generating...", "")
count, err := site.Build()
switch {
case err == nil:
elapsed := time.Since(commandStartTime)
logger.label("", "wrote %d files in %.2fs.", count, elapsed.Seconds())
case watch:
fmt.Fprintln(os.Stderr, err)
default:
return err
}
// FIXME the watch will miss files that changed during the first build
// server watch is implemented inside Server.Run, in contrast to this command
if watch {
events, err := site.WatchRebuild()
if err != nil {
return err
}
logger.label("Auto-regeneration", "enabled for %q\n", site.SourceDir())
for event := range events {
fmt.Print(event)
}
}
return nil
}
func cleanCommand(site *site.Site) error {
logger.label("Cleaner:", "Removing %s...", site.DestDir())
return site.Clean()
}
func benchmarkCommand() (err error) {
startTime := time.Now()
samples := []float64{}
for i := 0; time.Since(startTime) < 10*time.Second; i++ {
sampleStart := time.Now()
site, err := loadSite(*source, options)
if err != nil {
return err
}
_, err = site.Build()
if err != nil {
return err
}
dur := time.Since(sampleStart).Seconds()
samples = append(samples, dur)
quiet = true
fmt.Printf("Run #%d; %.1fs elapsed\n", i+1, time.Since(commandStartTime).Seconds())
}
median, _ := stats.Median(samples)
stddev, _ := stats.StandardDeviationSample(samples)
fmt.Printf("%d samples @ %.2fs ± %.2fs\n", len(samples), median, stddev)
return nil
}
func routesCommand(site *site.Site) error {
logger.label("Routes:", "")
urls := []string{}
for u, p := range site.Routes {
if !(*dynamicRoutes && p.Static()) {
urls = append(urls, u)
}
}
sort.Strings(urls)
for _, u := range urls {
filename := site.Routes[u].SourcePath()
fmt.Printf(" %s -> %s\n", u, filename)
}
return nil
}
func renderCommand(site *site.Site) error {
p, err := pageFromPathOrRoute(site, *renderPath)
if err != nil {
return err
}
logger.path("Render:", filepath.Join(site.SourceDir(), p.SourcePath()))
logger.label("URL:", p.Permalink())
logger.label("Content:", "")
return site.WriteDocument(os.Stdout, p)
}
// If path starts with /, it's a URL path. Else it's a file path relative
// to the site source directory.
func pageFromPathOrRoute(s *site.Site, path string) (pages.Document, error) {
if path == "" {
path = "/"
}
switch {
case strings.HasPrefix(path, "/"):
page, found := s.URLPage(path)
if !found {
return nil, utils.NewPathError("render", path, "the site does not include a file with this URL path")
}
return page, nil
default:
page, found := s.FilePathPage(path)
if !found {
return nil, utils.NewPathError("render", path, "no such file")
}
return page, nil
}
}
func serveCommand(site *site.Site) error {
server := server.Server{Site: site}
return server.Run(*open, func(label, value string) {
logger.label(label, value)
})
}
func variablesCommand(site *site.Site) (err error) {
var data interface{}
switch {
case strings.HasPrefix(*variablePath, "site"):
data, err = utils.FollowDots(site, strings.Split(*variablePath, ".")[1:])
if err != nil {
return
}
case *variablePath != "":
data, err = pageFromPathOrRoute(site, *variablePath)
if err != nil {
return
}
default:
data = site
}
b, err := yaml.Marshal(liquid.FromDrop(data))
if err != nil {
return err
}
logger.label("Variables:", "")
fmt.Println(string(b))
return nil
}
func versionCommand() error {
var d string
if !BuildTime.IsZero() {
d = BuildTime.Format(" (Build time: 2006-01-02T15:04)")
}
fmt.Printf("gojekyll version %s%s\n", Version, d)
return nil
}