mirror of
https://git.sr.ht/~adnano/kiln
synced 2024-10-30 01:13:08 +00:00
Refactor
This commit is contained in:
parent
3f38235d4b
commit
399e543b4a
2
go.mod
2
go.mod
|
@ -2,4 +2,4 @@ module kiln
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require git.sr.ht/~adnano/gmi v0.0.1-alpha
|
require git.sr.ht/~adnano/gmi v0.0.1-alpha.1
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,5 +1,5 @@
|
||||||
git.sr.ht/~adnano/gmi v0.0.1-alpha h1:6SRpwsKRowrKfExhyYQaQ0SBYcMIhHG4hUaWF67iP4k=
|
git.sr.ht/~adnano/gmi v0.0.1-alpha.1 h1:zXcPeenDDt3opygDCunf52x3IJdVFEc1V0wf8aHshzc=
|
||||||
git.sr.ht/~adnano/gmi v0.0.1-alpha/go.mod h1:4MWQDsleal4HRi/LuxxM6ymWJQikP3Gh7xZindVCHzg=
|
git.sr.ht/~adnano/gmi v0.0.1-alpha.1/go.mod h1:4MWQDsleal4HRi/LuxxM6ymWJQikP3Gh7xZindVCHzg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
|
213
kiln.go
213
kiln.go
|
@ -18,29 +18,42 @@ import (
|
||||||
|
|
||||||
// Site represents a kiln site.
|
// Site represents a kiln site.
|
||||||
type Site struct {
|
type Site struct {
|
||||||
URL string // Site URL
|
Title string // Site title.
|
||||||
Directory *Directory // Site directory
|
URL string // Site URL.
|
||||||
Templates *template.Template // Templates
|
dir *Dir // Site directory.
|
||||||
|
tmpl *template.Template // Templates.
|
||||||
|
feeds bool // Whether or not to generate feeds.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads the Site from the specified source directory.
|
// load loads the Site from the current directory.
|
||||||
func (s *Site) Load(srcDir string) error {
|
func (s *Site) load() error {
|
||||||
s.Directory = NewDirectory("")
|
// Load content
|
||||||
|
const srcDir = "src"
|
||||||
tmpl, err := template.New("templates").ParseGlob("templates/*.gmi")
|
s.dir = NewDir("")
|
||||||
if err != nil {
|
if err := site.dir.Read(srcDir, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Templates = tmpl
|
// Load templates
|
||||||
|
const tmplDir = "templates"
|
||||||
if err := site.Directory.Read(""); err != nil {
|
s.tmpl = template.New(tmplDir)
|
||||||
|
// Add default templates
|
||||||
|
s.tmpl.AddParseTree("atom.xml", atomTmpl.Tree)
|
||||||
|
s.tmpl.AddParseTree("index.gmi", indexTmpl.Tree)
|
||||||
|
s.tmpl.AddParseTree("page.gmi", pageTmpl.Tree)
|
||||||
|
// Add function to get site
|
||||||
|
s.tmpl = s.tmpl.Funcs(template.FuncMap{
|
||||||
|
"site": func() *Site { return s },
|
||||||
|
})
|
||||||
|
var err error
|
||||||
|
s.tmpl, err = s.tmpl.ParseGlob(filepath.Join(tmplDir, "*.gmi"))
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the contents of the Index to the provided destination directory.
|
// write writes the contents of the Index to the provided destination directory.
|
||||||
func (s *Site) Write(dstDir string, format OutputFormat) error {
|
func (s *Site) write(dstDir string, format OutputFormat) error {
|
||||||
// Empty the destination directory
|
// Empty the destination directory
|
||||||
if err := os.RemoveAll(dstDir); err != nil {
|
if err := os.RemoveAll(dstDir); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -49,105 +62,88 @@ func (s *Site) Write(dstDir string, format OutputFormat) error {
|
||||||
if err := os.MkdirAll(dstDir, 0755); err != nil {
|
if err := os.MkdirAll(dstDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the directory
|
// Write the directory
|
||||||
return s.Directory.Write(dstDir, format)
|
return s.dir.Write(dstDir, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manipulate processes and manipulates the site's content.
|
// manipulate processes and manipulates the site's content.
|
||||||
func (s *Site) Manipulate(dir *Directory) error {
|
func (s *Site) manipulate() error {
|
||||||
|
// FIXME: manipulate doesn't descend into subdirectories
|
||||||
// Write the directory index file, if it doesn't exist
|
// Write the directory index file, if it doesn't exist
|
||||||
if dir.Index == nil {
|
const indexPath = "index.gmi"
|
||||||
path := filepath.Join(dir.Permalink, "index.gmi")
|
if s.dir.index == nil {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
tmpl := s.Templates.Lookup("index.gmi")
|
tmpl := s.tmpl.Lookup(indexPath)
|
||||||
if tmpl == nil {
|
if err := tmpl.Execute(&b, s.dir); err != nil {
|
||||||
tmpl = indexTmpl
|
|
||||||
}
|
|
||||||
if err := tmpl.Execute(&b, dir); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
content := b.Bytes()
|
s.dir.index = &Page{
|
||||||
permalink := filepath.Dir(path)
|
Permalink: s.dir.Permalink,
|
||||||
if permalink == "." {
|
content: b.Bytes(),
|
||||||
permalink = ""
|
|
||||||
}
|
}
|
||||||
page := &Page{
|
|
||||||
Permalink: "/" + permalink,
|
|
||||||
content: content,
|
|
||||||
}
|
}
|
||||||
dir.Index = page
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manipulate pages
|
// Manipulate pages
|
||||||
for i := range dir.Pages {
|
const pagePath = "page.gmi"
|
||||||
|
for i := range s.dir.Pages {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
tmpl := s.Templates.Lookup("page.gmi")
|
tmpl := s.tmpl.Lookup(pagePath)
|
||||||
if tmpl == nil {
|
if err := tmpl.Execute(&b, s.dir.Pages[i]); err != nil {
|
||||||
tmpl = pageTmpl
|
|
||||||
}
|
|
||||||
if err := tmpl.Execute(&b, dir.Pages[i]); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dir.Pages[i].content = b.Bytes()
|
s.dir.Pages[i].content = b.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort sorts the site's pages by date.
|
// sort sorts the site's pages by date.
|
||||||
func (s *Site) Sort() {
|
func (s *Site) sort() {
|
||||||
s.Directory.Sort()
|
s.dir.Sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Feed represents a feed.
|
||||||
type Feed struct {
|
type Feed struct {
|
||||||
Title string
|
Title string // Feed title.
|
||||||
Path string
|
Path string // Feed path.
|
||||||
SiteURL string
|
URL string // Site URL.
|
||||||
Updated time.Time
|
Updated time.Time // Last updated time.
|
||||||
Entries []*Page
|
Entries []*Page // Feed entries.
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFeeds creates Atom feeds.
|
// createFeeds creates Atom feeds.
|
||||||
func (s *Site) CreateFeeds() error {
|
func (s *Site) createFeeds() error {
|
||||||
const atomPath = "atom.xml"
|
const atomPath = "atom.xml"
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
tmpl := s.Templates.Lookup(atomPath)
|
tmpl := s.tmpl.Lookup(atomPath)
|
||||||
if tmpl == nil {
|
|
||||||
tmpl = atomTmpl
|
|
||||||
}
|
|
||||||
feed := &Feed{
|
feed := &Feed{
|
||||||
Title: "Example Feed",
|
Title: s.Title,
|
||||||
Path: filepath.Join(s.Directory.Permalink, atomPath),
|
Path: filepath.Join(s.dir.Permalink, atomPath),
|
||||||
SiteURL: s.URL,
|
URL: s.URL,
|
||||||
Updated: time.Now(),
|
Updated: time.Now(),
|
||||||
Entries: s.Directory.Pages,
|
Entries: s.dir.Pages,
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(&b, feed); err != nil {
|
if err := tmpl.Execute(&b, feed); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
path := filepath.Join(s.Directory.Permalink, atomPath)
|
path := filepath.Join(s.dir.Permalink, atomPath)
|
||||||
s.Directory.Static[path] = b.Bytes()
|
s.dir.Files[path] = b.Bytes()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page represents a page.
|
// Page represents a page.
|
||||||
type Page struct {
|
type Page struct {
|
||||||
// The permalink to this page.
|
Title string // The title of this page.
|
||||||
Permalink string
|
Permalink string // The permalink to this page.
|
||||||
// The title of this page, parsed from the Gemini contents.
|
Date time.Time // The date of the page.
|
||||||
Title string
|
content []byte // The content of this page.
|
||||||
// The date of the page. Dates are specified in the filename.
|
|
||||||
// Ex: 2020-09-22-hello-world.gmi
|
|
||||||
Date time.Time
|
|
||||||
// The content of this page.
|
|
||||||
content []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Content returns the page content as a string.
|
||||||
|
// Used in templates.
|
||||||
func (p *Page) Content() string {
|
func (p *Page) Content() string {
|
||||||
return string(p.content)
|
return string(p.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regexp to parse title from Gemini files
|
||||||
var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)\r?\n?\r?\n?")
|
var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)\r?\n?\r?\n?")
|
||||||
|
|
||||||
// NewPage returns a new Page with the given path and content.
|
// NewPage returns a new Page with the given path and content.
|
||||||
|
@ -196,82 +192,77 @@ func NewPage(path string, content []byte) *Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directory represents a directory of pages.
|
// Dir represents a directory.
|
||||||
type Directory struct {
|
type Dir struct {
|
||||||
// The permalink to this directory.
|
Permalink string // Permalink to this directory.
|
||||||
Permalink string
|
Pages []*Page // Pages in this directory.
|
||||||
// The pages in this directory.
|
Dirs []*Dir // Subdirectories.
|
||||||
Pages []*Page
|
Files map[string][]byte // Static files.
|
||||||
// The subdirectories of this directory.
|
index *Page // The index file (index.gmi).
|
||||||
Directories []*Directory
|
|
||||||
// The index file (index.gmi).
|
|
||||||
Index *Page
|
|
||||||
// Static files
|
|
||||||
Static map[string][]byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDirectory returns a new Directory with the given path.
|
// NewDir returns a new Dir with the given path.
|
||||||
func NewDirectory(path string) *Directory {
|
func NewDir(path string) *Dir {
|
||||||
var permalink string
|
var permalink string
|
||||||
if path == "" {
|
if path == "" {
|
||||||
permalink = "/"
|
permalink = "/"
|
||||||
} else {
|
} else {
|
||||||
permalink = "/" + path + "/"
|
permalink = "/" + path + "/"
|
||||||
}
|
}
|
||||||
return &Directory{
|
return &Dir{
|
||||||
Permalink: permalink,
|
Permalink: permalink,
|
||||||
Static: map[string][]byte{},
|
Files: map[string][]byte{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads from a directory and indexes the files and directories within it.
|
// Read reads from a directory and indexes the files and directories within it.
|
||||||
func (d *Directory) Read(path string) error {
|
func (d *Dir) Read(srcDir string, path string) error {
|
||||||
entries, err := ioutil.ReadDir(filepath.Join("src", path))
|
entries, err := ioutil.ReadDir(filepath.Join(srcDir, path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
name := entry.Name()
|
name := entry.Name()
|
||||||
|
// Ignore names that start with '_'
|
||||||
|
if strings.HasPrefix(name, "_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path := filepath.Join(path, name)
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
// Gather directory data
|
// Gather directory data
|
||||||
path := filepath.Join(path, name)
|
dir := NewDir(path)
|
||||||
dir := NewDirectory(path)
|
if err := dir.Read(srcDir, path); err != nil {
|
||||||
if err := dir.Read(path); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.Directories = append(d.Directories, dir)
|
d.Dirs = append(d.Dirs, dir)
|
||||||
} else {
|
} else {
|
||||||
srcPath := filepath.Join("src", path, name)
|
srcPath := filepath.Join(srcDir, path)
|
||||||
content, err := ioutil.ReadFile(srcPath)
|
content, err := ioutil.ReadFile(srcPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch filepath.Ext(name) {
|
switch filepath.Ext(name) {
|
||||||
case ".gmi", ".gemini":
|
case ".gmi":
|
||||||
path := filepath.Join(path, name)
|
|
||||||
// Gather page data
|
// Gather page data
|
||||||
page := NewPage(path, content)
|
page := NewPage(path, content)
|
||||||
|
|
||||||
if name == "index.gmi" {
|
if name == "index.gmi" {
|
||||||
d.Index = page
|
d.index = page
|
||||||
} else {
|
} else {
|
||||||
d.Pages = append(d.Pages, page)
|
d.Pages = append(d.Pages, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Static file
|
// Static file
|
||||||
path := filepath.Join(path, name)
|
d.Files[path] = content
|
||||||
d.Static[path] = content
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the Directory to the provided destination path.
|
// Write writes the Dir to the provided destination path.
|
||||||
func (d *Directory) Write(dstDir string, format OutputFormat) error {
|
func (d *Dir) Write(dstDir string, format OutputFormat) error {
|
||||||
// Create the directory
|
// Create the directory
|
||||||
dirPath := filepath.Join(dstDir, d.Permalink)
|
dirPath := filepath.Join(dstDir, d.Permalink)
|
||||||
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
||||||
|
@ -279,13 +270,13 @@ func (d *Directory) Write(dstDir string, format OutputFormat) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write static files
|
// Write static files
|
||||||
for path := range d.Static {
|
for path := range d.Files {
|
||||||
dstPath := filepath.Join(dstDir, path)
|
dstPath := filepath.Join(dstDir, path)
|
||||||
f, err := os.Create(dstPath)
|
f, err := os.Create(dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data := d.Static[path]
|
data := d.Files[path]
|
||||||
if _, err := f.Write(data); err != nil {
|
if _, err := f.Write(data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -307,8 +298,8 @@ func (d *Directory) Write(dstDir string, format OutputFormat) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the index file
|
// Write the index file
|
||||||
if d.Index != nil {
|
if d.index != nil {
|
||||||
path, content := format(d.Index)
|
path, content := format(d.index)
|
||||||
dstPath := filepath.Join(dstDir, path)
|
dstPath := filepath.Join(dstDir, path)
|
||||||
f, err := os.Create(dstPath)
|
f, err := os.Create(dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -320,19 +311,19 @@ func (d *Directory) Write(dstDir string, format OutputFormat) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write subdirectories
|
// Write subdirectories
|
||||||
for _, dir := range d.Directories {
|
for _, dir := range d.Dirs {
|
||||||
dir.Write(dstDir, format)
|
dir.Write(dstDir, format)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort sorts the directory's pages by date.
|
// Sort sorts the directory's pages by date.
|
||||||
func (d *Directory) Sort() {
|
func (d *Dir) Sort() {
|
||||||
sort.Slice(d.Pages, func(i, j int) bool {
|
sort.Slice(d.Pages, func(i, j int) bool {
|
||||||
return d.Pages[i].Date.After(d.Pages[j].Date)
|
return d.Pages[i].Date.After(d.Pages[j].Date)
|
||||||
})
|
})
|
||||||
// Sort subdirectories
|
// Sort subdirectories
|
||||||
for _, d := range d.Directories {
|
for _, d := range d.Dirs {
|
||||||
d.Sort()
|
d.Sort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
main.go
13
main.go
|
@ -19,6 +19,7 @@ func init() {
|
||||||
flag.BoolVar(&serveSite, "serve", false, "serve the site")
|
flag.BoolVar(&serveSite, "serve", false, "serve the site")
|
||||||
flag.BoolVar(&toHtml, "html", false, "output HTML")
|
flag.BoolVar(&toHtml, "html", false, "output HTML")
|
||||||
flag.BoolVar(&toAtom, "atom", false, "output Atom feed")
|
flag.BoolVar(&toAtom, "atom", false, "output Atom feed")
|
||||||
|
flag.StringVar(&site.Title, "title", "", "site title")
|
||||||
flag.StringVar(&site.URL, "url", "", "site URL")
|
flag.StringVar(&site.URL, "url", "", "site URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,23 +36,23 @@ func main() {
|
||||||
|
|
||||||
// build the site
|
// build the site
|
||||||
func build() error {
|
func build() error {
|
||||||
if err := site.Load("src"); err != nil {
|
if err := site.load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
site.Sort()
|
site.sort()
|
||||||
if err := site.Manipulate(site.Directory); err != nil {
|
if err := site.manipulate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if toAtom {
|
if toAtom {
|
||||||
if err := site.CreateFeeds(); err != nil {
|
if err := site.createFeeds(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := site.Write("dst", OutputGemini); err != nil {
|
if err := site.write("dst", OutputGemini); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if toHtml {
|
if toHtml {
|
||||||
if err := site.Write("dst.html", OutputHTML); err != nil {
|
if err := site.write("dst.html", OutputHTML); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
templates.go
24
templates.go
|
@ -7,28 +7,28 @@ import "text/template"
|
||||||
const atom_xml = `<?xml version="1.0" encoding="utf-8"?>
|
const atom_xml = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<title>{{ .Title }}</title>
|
<title>{{ .Title }}</title>
|
||||||
<link href="{{ .SiteURL }}"/>
|
<link href="{{ .URL }}"/>
|
||||||
<link rel="self" href="{{ .SiteURL }}{{ .Path }}"/>
|
<link rel="self" href="{{ .URL }}{{ .Path }}"/>
|
||||||
<updated>{{ .Updated }}</updated>
|
<updated>{{ .Updated }}</updated>
|
||||||
<id>{{ .SiteURL }}{{ .Path }}</id>
|
<id>{{ .URL }}{{ .Path }}</id>
|
||||||
{{ $siteURL := .SiteURL }}
|
{{- $url := .URL -}}
|
||||||
{{ range .Entries }}
|
{{- range .Entries }}
|
||||||
<entry>
|
<entry>
|
||||||
<title>{{ .Title }}</title>
|
<title>{{ .Title }}</title>
|
||||||
<link href="{{ $siteURL }}{{ .Permalink }}"/>
|
<link href="{{ $url }}{{ .Permalink }}"/>
|
||||||
<id>{{ $siteURL }}{{ .Permalink }}</id>
|
<id>{{ $url }}{{ .Permalink }}</id>
|
||||||
<updated>{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</updated>
|
<updated>{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</updated>
|
||||||
<content src="{{ $siteURL }}{{ .Permalink }}" type="text/gemini"></content>
|
<content src="{{ $url }}{{ .Permalink }}" type="text/gemini"></content>
|
||||||
</entry>
|
</entry>
|
||||||
{{ end }}
|
{{ end -}}
|
||||||
</feed>`
|
</feed>`
|
||||||
|
|
||||||
const index_gmi = `# Index of {{ .Permalink }}
|
const index_gmi = `# Index of {{ .Permalink }}
|
||||||
|
|
||||||
{{ range .Directories }}=> {{ .Permalink }}
|
{{ range .Dirs }}=> {{ .Permalink }}
|
||||||
{{ end }}
|
{{ end -}}
|
||||||
{{ range .Pages }}=> {{ .Permalink }}
|
{{ range .Pages }}=> {{ .Permalink }}
|
||||||
{{ end }}`
|
{{ end -}}`
|
||||||
|
|
||||||
const page_gmi = `# {{ .Title }}
|
const page_gmi = `# {{ .Title }}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue