From d0713476c0a5ef57be21d8273c947dd865bf6df5 Mon Sep 17 00:00:00 2001 From: adnano Date: Tue, 22 Sep 2020 19:46:30 -0400 Subject: [PATCH] Refactor --- index.go | 80 ------------------- kiln.go | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 85 +------------------- manipulate.go | 66 ---------------- 4 files changed, 215 insertions(+), 228 deletions(-) delete mode 100644 index.go create mode 100644 kiln.go delete mode 100644 manipulate.go diff --git a/index.go b/index.go deleted file mode 100644 index d344914..0000000 --- a/index.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - "io/ioutil" - "os" - "path/filepath" -) - -type Index struct { - Files map[string][]byte - Dirs map[string][]string -} - -func NewIndex() *Index { - return &Index{ - Files: map[string][]byte{}, - Dirs: map[string][]string{}, - } -} - -// ReadDir reads a directory and indexes the files and directories within it. -func (index *Index) ReadDir(srcDir string, dstDir string) error { - entries, err := ioutil.ReadDir(srcDir) - if err != nil { - return err - } - - for _, entry := range entries { - name := entry.Name() - srcPath := filepath.Join(srcDir, name) - dstPath := filepath.Join(dstDir, name) - - if entry.IsDir() { - index.Dirs[dstPath] = []string{} - index.ReadDir(srcPath, dstPath) - } else { - content, err := ioutil.ReadFile(srcPath) - if err != nil { - return err - } - - index.Files[dstPath] = content - index.Dirs[dstDir] = append(index.Dirs[dstDir], dstPath) - } - } - return nil -} - -// Write writes the contents of the Index to the provided destination directory. -func (index *Index) Write(dstDir string) error { - // Empty the destination directory - if err := os.RemoveAll(dstDir); err != nil { - return err - } - if err := os.MkdirAll(dstDir, 0755); err != nil { - return err - } - - for path := range index.Files { - // Create any parent directories - if dir := filepath.Dir(path); dir != "." { - dstPath := filepath.Join(dstDir, dir) - if err := os.MkdirAll(dstPath, 0755); err != nil { - return err - } - } - - // Write the file - dstPath := filepath.Join(dstDir, path) - f, err := os.Create(dstPath) - if err != nil { - return err - } - data := index.Files[path] - if _, err := f.Write(data); err != nil { - return err - } - } - return nil -} diff --git a/kiln.go b/kiln.go new file mode 100644 index 0000000..7af17fc --- /dev/null +++ b/kiln.go @@ -0,0 +1,212 @@ +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + "text/template" + "time" +) + +type Site struct { + Files map[string][]byte + Dirs map[string][]string + Pages map[string]*Page + Templates *template.Template +} + +func LoadSite(srcDir string) (*Site, error) { + tmpl, err := template.New("templates").ParseGlob("templates/*.gmi") + if err != nil { + return nil, err + } + + site := &Site{ + Files: map[string][]byte{}, + Dirs: map[string][]string{}, + Pages: map[string]*Page{}, + Templates: tmpl, + } + + if err := site.ReadDir(srcDir, ""); err != nil { + return nil, err + } + + return site, nil +} + +// ReadDir reads a directory and indexes the files and directories within it. +func (s *Site) ReadDir(srcDir string, dstDir string) error { + entries, err := ioutil.ReadDir(srcDir) + if err != nil { + return err + } + + for _, entry := range entries { + name := entry.Name() + srcPath := filepath.Join(srcDir, name) + dstPath := filepath.Join(dstDir, name) + + if entry.IsDir() { + s.Dirs[dstPath] = []string{} + s.ReadDir(srcPath, dstPath) + } else { + content, err := ioutil.ReadFile(srcPath) + if err != nil { + return err + } + + s.Files[dstPath] = content + s.Dirs[dstDir] = append(s.Dirs[dstDir], dstPath) + } + } + return nil +} + +// Write writes the contents of the Index to the provided destination directory. +func (s *Site) Write(dstDir string) error { + // Empty the destination directory + if err := os.RemoveAll(dstDir); err != nil { + return err + } + if err := os.MkdirAll(dstDir, 0755); err != nil { + return err + } + + for path := range s.Files { + // Create any parent directories + if dir := filepath.Dir(path); dir != "." { + dstPath := filepath.Join(dstDir, dir) + if err := os.MkdirAll(dstPath, 0755); err != nil { + return err + } + } + + // Write the file + dstPath := filepath.Join(dstDir, path) + f, err := os.Create(dstPath) + if err != nil { + return err + } + data := s.Files[path] + if _, err := f.Write(data); err != nil { + return err + } + } + return nil +} + +// Manipulate processes and manipulates the site's content. +func (s *Site) Manipulate() error { + for path := range s.Files { + switch filepath.Ext(path) { + case ".gmi": + // Gather page data + content := string(s.Files[path]) + page := NewPage(path, content) + + builder := &strings.Builder{} + tmpl := s.Templates.Lookup("page.gmi") + if err := tmpl.Execute(builder, page); err != nil { + return err + } + page.Content = builder.String() + s.Pages[path] = page + s.Files[path] = []byte(page.Content) + } + } + + for dir := range s.Dirs { + // Gather section data + section := NewSection(dir) + for _, path := range s.Dirs[dir] { + switch filepath.Ext(path) { + case ".gmi": + section.Pages = append(section.Pages, s.Pages[path]) + } + } + + dstPath := filepath.Join(dir, "index.gmi") + builder := &strings.Builder{} + tmpl := s.Templates.Lookup("section.gmi") + if err := tmpl.Execute(builder, section); err != nil { + return err + } + s.Files[dstPath] = []byte(builder.String()) + } + + return nil +} + +// Page represents a page. +type Page struct { + // The path to this page. + Path string + // The permalink to this page. + Permalink string + // The title of this page, parsed from the Gemini contents. + Title string + // 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 string +} + +var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)") + +func NewPage(path string, content string) *Page { + page := &Page{ + Path: path, + Permalink: "/" + path, + Content: content, + } + + // Try to parse the date from the page filename + const layout = "2006-01-02" + base := filepath.Base(path) + if len(base) >= len(layout) { + dateStr := base[:len(layout)] + if date, err := time.Parse(layout, dateStr); err == nil { + page.Date = date + } + } + + // Try to parse the title from the contents + if submatches := titleRE.FindStringSubmatch(content); submatches != nil { + page.Title = submatches[1] + } + + return page +} + +// Section represents a section (i.e., a directory). +type Section struct { + // The path to this section. + Path string + // The permalink to this section. + Permalink string + // The pages in this section. + Pages []*Page +} + +// NewSection returns a new Section with the given path. +func NewSection(path string) *Section { + var permalink string + if path == "" { + permalink = "/" + } else { + permalink = "/" + path + "/" + } + return &Section{ + Path: path, + Permalink: permalink, + } +} + +// Sort sorts pages by date. +func (s *Section) Sort() { + // TODO: Implement this +} diff --git a/main.go b/main.go index 1a3410d..8e3da6c 100644 --- a/main.go +++ b/main.go @@ -2,9 +2,6 @@ package main import ( "log" - "path/filepath" - "regexp" - "time" ) func main() { @@ -14,91 +11,15 @@ func main() { } func run() error { - index := NewIndex() - if err := index.ReadDir("src", ""); err != nil { - return err - } - manipulator, err := NewManipulator() + site, err := LoadSite("src") if err != nil { return err } - if err := manipulator.Manipulate(index); err != nil { + if err := site.Manipulate(); err != nil { return err } - - if err := index.Write("dst"); err != nil { + if err := site.Write("dst"); err != nil { return err } return nil } - -// Page represents a page. -type Page struct { - // The path to this page. - Path string - // The permalink to this page. - Permalink string - // The title of this page, parsed from the Gemini contents. - Title string - // 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 string -} - -var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)") - -func NewPage(path string, content string) *Page { - page := &Page{ - Path: path, - Permalink: "/" + path, - Content: content, - } - - // Try to parse the date from the page filename - const layout = "2006-01-02" - base := filepath.Base(path) - if len(base) >= len(layout) { - dateStr := base[:len(layout)] - if date, err := time.Parse(layout, dateStr); err == nil { - page.Date = date - } - } - - // Try to parse the title from the contents - if submatches := titleRE.FindStringSubmatch(content); submatches != nil { - page.Title = submatches[1] - } - - return page -} - -// Section represents a section (i.e., a directory). -type Section struct { - // The path to this section. - Path string - // The permalink to this section. - Permalink string - // The pages in this section. - Pages []*Page -} - -// NewSection returns a new Section with the given path. -func NewSection(path string) *Section { - var permalink string - if path == "" { - permalink = "/" - } else { - permalink = "/" + path + "/" - } - return &Section{ - Path: path, - Permalink: permalink, - } -} - -// Sort sorts pages by date. -func (s *Section) Sort() { - // TODO: Implement this -} diff --git a/manipulate.go b/manipulate.go deleted file mode 100644 index 11ada01..0000000 --- a/manipulate.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "path/filepath" - "strings" - "text/template" -) - -type Manipulator struct { - Pages map[string]*Page - - // Templates - Templates *template.Template -} - -func NewManipulator() (*Manipulator, error) { - tmpl, err := template.New("templates").ParseGlob("templates/*.gmi") - if err != nil { - return nil, err - } - return &Manipulator{ - Pages: map[string]*Page{}, - Templates: tmpl, - }, nil -} - -func (m *Manipulator) Manipulate(index *Index) error { - for path := range index.Files { - switch filepath.Ext(path) { - case ".gmi": - // Gather page data - content := string(index.Files[path]) - page := NewPage(path, content) - - builder := &strings.Builder{} - tmpl := m.Templates.Lookup("page.gmi") - if err := tmpl.Execute(builder, page); err != nil { - return err - } - page.Content = builder.String() - m.Pages[path] = page - index.Files[path] = []byte(page.Content) - } - } - - for dir := range index.Dirs { - // Load section data - section := NewSection(dir) - for _, path := range index.Dirs[dir] { - switch filepath.Ext(path) { - case ".gmi": - section.Pages = append(section.Pages, m.Pages[path]) - } - } - - dstPath := filepath.Join(dir, "index.gmi") - builder := &strings.Builder{} - tmpl := m.Templates.Lookup("section.gmi") - if err := tmpl.Execute(builder, section); err != nil { - return err - } - index.Files[dstPath] = []byte(builder.String()) - } - - return nil -}