2017-06-17 16:51:32 +02:00
|
|
|
package gojekyll
|
2017-06-15 13:31:52 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-06-16 01:49:04 +02:00
|
|
|
"path"
|
2017-06-15 13:31:52 +02:00
|
|
|
"path/filepath"
|
2017-06-15 16:17:21 +02:00
|
|
|
"regexp"
|
2017-06-16 04:32:10 +02:00
|
|
|
"strings"
|
2017-06-15 15:01:42 +02:00
|
|
|
"time"
|
2017-06-17 01:17:22 +02:00
|
|
|
|
2017-06-17 02:11:52 +02:00
|
|
|
"github.com/osteele/gojekyll/helpers"
|
2017-06-15 13:31:52 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// PermalinkStyles defines built-in styles from https://jekyllrb.com/docs/permalinks/#builtinpermalinkstyles
|
|
|
|
var PermalinkStyles = map[string]string{
|
|
|
|
"date": "/:categories/:year/:month/:day/:title.html",
|
|
|
|
"pretty": "/:categories/:year/:month/:day/:title/",
|
|
|
|
"ordinal": "/:categories/:year/:y_day/:title.html",
|
|
|
|
"none": "/:categories/:title.html",
|
|
|
|
}
|
|
|
|
|
2017-06-15 15:01:42 +02:00
|
|
|
// permalinkDateVariables maps Jekyll permalink template variable names
|
|
|
|
// to time.Format layout strings
|
|
|
|
var permalinkDateVariables = map[string]string{
|
|
|
|
"month": "01",
|
|
|
|
"imonth": "1",
|
|
|
|
"day": "02",
|
|
|
|
"i_day": "2",
|
|
|
|
"hour": "15",
|
|
|
|
"minute": "04",
|
|
|
|
"second": "05",
|
|
|
|
"year": "2006",
|
|
|
|
"short_year": "06",
|
|
|
|
}
|
|
|
|
|
2017-06-15 16:17:21 +02:00
|
|
|
var templateVariableMatcher = regexp.MustCompile(`:\w+\b`)
|
|
|
|
|
2017-06-15 15:01:42 +02:00
|
|
|
// See https://jekyllrb.com/docs/permalinks/#template-variables
|
2017-06-16 20:52:29 +02:00
|
|
|
func (p *pageFields) permalinkTemplateVariables() map[string]string {
|
2017-06-15 13:31:52 +02:00
|
|
|
var (
|
|
|
|
collectionName string
|
2017-06-17 02:06:55 +02:00
|
|
|
path = p.relpath
|
2017-06-15 13:31:52 +02:00
|
|
|
ext = filepath.Ext(path)
|
|
|
|
outputExt = ext
|
2017-06-17 02:11:52 +02:00
|
|
|
root = helpers.PathWithoutExtension(path)
|
2017-06-15 13:31:52 +02:00
|
|
|
name = filepath.Base(root)
|
2017-06-16 20:52:29 +02:00
|
|
|
title = p.frontMatter.String("title", name)
|
2017-06-15 13:31:52 +02:00
|
|
|
)
|
2017-06-16 04:32:10 +02:00
|
|
|
switch {
|
2017-06-16 21:14:56 +02:00
|
|
|
case p.site.IsMarkdown(path):
|
2017-06-16 04:32:10 +02:00
|
|
|
outputExt = ".html"
|
2017-06-16 21:14:56 +02:00
|
|
|
case p.site.IsSassPath(path):
|
2017-06-16 19:47:11 +02:00
|
|
|
outputExt = ".css"
|
2017-06-15 13:31:52 +02:00
|
|
|
}
|
2017-06-17 02:19:46 +02:00
|
|
|
if p.collection != nil {
|
|
|
|
root = strings.TrimPrefix(root, p.collection.PathPrefix())
|
2017-06-15 13:31:52 +02:00
|
|
|
}
|
2017-06-15 15:01:42 +02:00
|
|
|
vs := map[string]string{
|
2017-06-15 13:31:52 +02:00
|
|
|
"collection": collectionName,
|
2017-06-17 02:11:52 +02:00
|
|
|
"name": helpers.Slugify(name),
|
2017-06-16 04:32:10 +02:00
|
|
|
"path": "/" + root,
|
2017-06-16 01:49:04 +02:00
|
|
|
"title": title,
|
2017-06-17 02:11:52 +02:00
|
|
|
"slug": helpers.Slugify(name),
|
2017-06-16 01:49:04 +02:00
|
|
|
// TODO categories
|
|
|
|
// The following isn't documented, but is evident
|
2017-06-15 15:01:42 +02:00
|
|
|
"output_ext": outputExt,
|
|
|
|
}
|
|
|
|
d := time.Now() // TODO read from frontMatter or use file modtime
|
|
|
|
for name, f := range permalinkDateVariables {
|
|
|
|
vs[name] = d.Format(f)
|
2017-06-15 13:31:52 +02:00
|
|
|
}
|
2017-06-15 15:01:42 +02:00
|
|
|
return vs
|
2017-06-15 13:31:52 +02:00
|
|
|
}
|
|
|
|
|
2017-06-16 20:52:29 +02:00
|
|
|
func (p *pageFields) expandPermalink() (s string, err error) {
|
|
|
|
pattern := p.frontMatter.String("permalink", ":path:output_ext")
|
2017-06-15 13:31:52 +02:00
|
|
|
if p, found := PermalinkStyles[pattern]; found {
|
|
|
|
pattern = p
|
|
|
|
}
|
2017-06-16 20:52:29 +02:00
|
|
|
templateVariables := p.permalinkTemplateVariables()
|
2017-06-15 13:31:52 +02:00
|
|
|
// The ReplaceAllStringFunc callback signals errors via panic.
|
|
|
|
// Turn them into return values.
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
if e, ok := r.(error); ok {
|
|
|
|
err = e
|
|
|
|
} else {
|
|
|
|
panic(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
s = templateVariableMatcher.ReplaceAllStringFunc(pattern, func(m string) string {
|
|
|
|
varname := m[1:]
|
|
|
|
value, found := templateVariables[varname]
|
|
|
|
if !found {
|
|
|
|
panic(fmt.Errorf("unknown variable %s in permalink template %s", varname, pattern))
|
|
|
|
}
|
|
|
|
return value
|
|
|
|
})
|
2017-06-17 06:12:09 +02:00
|
|
|
return path.Clean(filepath.ToSlash(s)), nil
|
2017-06-15 13:31:52 +02:00
|
|
|
}
|
2017-06-16 20:52:29 +02:00
|
|
|
|
|
|
|
// The permalink is computed once instead of on demand, so that subsequent
|
|
|
|
// access needn't check for an error.
|
|
|
|
func (p *pageFields) initPermalink() (err error) {
|
|
|
|
p.permalink, err = p.expandPermalink()
|
|
|
|
return
|
|
|
|
}
|