in internal/web/page.go [35:119]
func (site *Site) openPage(file string) (*pageFile, error) {
// Strip trailing .html or .md or /; it all names the same page.
if strings.HasSuffix(file, "/index.md") {
file = strings.TrimSuffix(file, "/index.md")
} else if strings.HasSuffix(file, "/index.html") {
file = strings.TrimSuffix(file, "/index.html")
} else if file == "index.md" || file == "index.html" {
file = "."
} else if strings.HasSuffix(file, "/") {
file = strings.TrimSuffix(file, "/")
} else if strings.HasSuffix(file, ".html") {
file = strings.TrimSuffix(file, ".html")
} else {
file = strings.TrimSuffix(file, ".md")
}
now := time.Now().UnixNano()
if cp, ok := site.cache.Load(file); ok {
// Have cache entry; only use if the underlying file hasn't changed.
// To avoid continuous stats, only check it has been 3s since the last one.
// TODO(rsc): Move caching into a more general layer and cache templates.
p := cp.(*pageFile)
if now-atomic.LoadInt64(&p.checked) >= 3e9 {
info, err := fs.Stat(site.fs, p.file)
if err == nil && info.ModTime().Equal(p.stat.ModTime()) && info.Size() == p.stat.Size() {
atomic.StoreInt64(&p.checked, now)
return p, nil
}
}
}
// Check md before html to work correctly when x/website is layered atop Go 1.15 goroot during Go 1.15 tests.
// Want to find x/website's debugging_with_gdb.md not Go 1.15's debuging_with_gdb.html.
files := []string{file + ".md", file + ".html", path.Join(file, "index.md"), path.Join(file, "index.html")}
var filePath string
var b []byte
var err error
var stat fs.FileInfo
for _, filePath = range files {
stat, err = fs.Stat(site.fs, filePath)
if err == nil {
b, err = site.readFile(".", filePath)
if err == nil {
break
}
}
}
if err != nil {
return nil, err
}
// If we read an index.md or index.html, the canonical relpath is without the index.md/index.html suffix.
url := path.Join("/", file)
if name := path.Base(filePath); name == "index.html" || name == "index.md" {
url, _ = path.Split(path.Join("/", filePath))
}
params, body, err := parseMeta(b)
if err != nil {
return nil, err
}
p := &pageFile{
file: filePath,
stat: stat,
url: url,
data: body,
page: params,
checked: now,
}
// File, FileData, URL
p.page["File"] = filePath
p.page["FileData"] = string(body)
p.page["URL"] = p.url
// User-specified redirect: overrides url but not URL.
if redir, _ := p.page["redirect"].(string); redir != "" {
p.url = redir
}
site.cache.Store(file, p)
return p, nil
}