package main import ( "log" "path/filepath" "regexp" "time" ) func main() { if err := run(); err != nil { log.Fatal(err) } } func run() error { index := NewIndex() if err := index.ReadDir("src", ""); err != nil { return err } manipulator, err := NewManipulator() if err != nil { return err } if err := manipulator.Manipulate(index); err != nil { return err } if err := index.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 }