diff options
Diffstat (limited to 'hswg')
-rw-r--r-- | hswg/main.go | 195 |
1 files changed, 112 insertions, 83 deletions
diff --git a/hswg/main.go b/hswg/main.go index 5076bd1..a23e343 100644 --- a/hswg/main.go +++ b/hswg/main.go @@ -187,49 +187,61 @@ func expand(m *map[string]*Entry, name string, chunk []byte) []byte { }) } -func singleFile() { - html, meta, err := Render(os.Stdin, configuration.NewConfiguration()) +var tagRE = regexp.MustCompile(`<[^<>]+>`) + +func renderEntry(name string, entries *map[string]*Entry) error { + e := (*entries)[name] + + f, err := os.Open(e.PathSource) if err != nil { - log.Println(err) - } else if meta.Title != "" { - _, _ = os.Stdout.WriteString("<h1>") - _ = xml.EscapeText(os.Stdout, []byte(meta.Title)) - _, _ = os.Stdout.WriteString("</h1>\n") + return err } - _, _ = io.Copy(os.Stdout, html) -} -func main() { - if len(os.Args) < 2 { - singleFile() - return + if i, err := f.Stat(); err != nil { + return err + } else { + e.mtime = i.ModTime() } - if len(os.Args) < 3 { - log.Fatalf("usage: %s TEMPLATE GLOB...\n", os.Args[0]) + + var html *bytes.Buffer + if html, e.Metadata, err = Render(f, configuration.NewConfiguration( + configuration.WithFilename(e.PathSource), + configuration.WithLastUpdated(e.mtime), + )); err != nil { + return err } - // Read the common page header. - header, err := ioutil.ReadFile(os.Args[1]) - if err != nil { - log.Fatalln(err) + // Every page needs to have a title. + if e.Title == "" { + e.Title = name } - t, err := template.New("page").Parse(string(header)) - if err != nil { - log.Fatalln(err) + // Expand LinkWords anywhere between <tags>. + // We want something like the inverse of Regexp.ReplaceAllStringFunc. + raw, last, expanded := html.Bytes(), 0, bytes.NewBuffer(nil) + for _, where := range tagRE.FindAllIndex(raw, -1) { + _, _ = expanded.Write(expand(entries, name, raw[last:where[0]])) + _, _ = expanded.Write(raw[where[0]:where[1]]) + last = where[1] } + _, _ = expanded.Write(expand(entries, name, raw[last:])) + e.Content = template.HTML(expanded.String()) + return nil +} +func loadEntries(globs []string) (map[string]*Entry, error) { // Create a map from document names to their page entries. entries := map[string]*Entry{} - for _, glob := range os.Args[2:] { + for _, glob := range globs { matches, err := filepath.Glob(glob) if err != nil { - log.Fatalf("%s: %s\n", glob, err) + return nil, fmt.Errorf("%s: %s\n", glob, err) } for _, path := range matches { name := stripExtension(filepath.Base(path)) if conflict, ok := entries[name]; ok { - log.Fatalf("%s: conflicts with %s\n", name, conflict.PathSource) + return nil, fmt.Errorf("%s: conflicts with %s\n", + name, conflict.PathSource) } entries[name] = &Entry{ PathSource: path, @@ -239,68 +251,38 @@ func main() { } } - tagRE := regexp.MustCompile(`<[^<>]+>`) - for name, e := range entries { - f, err := os.Open(e.PathSource) - if err != nil { - log.Fatalln(err) - } - - if i, err := f.Stat(); err != nil { - log.Fatalln(err) - } else { - e.mtime = i.ModTime() - } - - var html *bytes.Buffer - if html, e.Metadata, err = Render(f, configuration.NewConfiguration( - configuration.WithFilename(e.PathSource), - configuration.WithLastUpdated(e.mtime), - )); err != nil { - log.Fatalln(err) - } - - // Every page needs to have a title. - if e.Title == "" { - e.Title = name - } - - // Expand LinkWords anywhere between <tags>. - // We want something like the inverse of Regexp.ReplaceAllStringFunc. - raw, last, expanded := html.Bytes(), 0, bytes.NewBuffer(nil) - for _, where := range tagRE.FindAllIndex(raw, -1) { - _, _ = expanded.Write(expand(&entries, name, raw[last:where[0]])) - _, _ = expanded.Write(raw[where[0]:where[1]]) - last = where[1] + for name := range entries { + if err := renderEntry(name, &entries); err != nil { + return nil, err } - _, _ = expanded.Write(expand(&entries, name, raw[last:])) - e.Content = template.HTML(expanded.String()) } + return entries, nil +} - for _, e := range entries { - f, err := os.Create(e.PathDestination) - if err != nil { - log.Fatalln(err) - } - - backlinks := []string{} - for name := range e.backlinks { - backlinks = append(backlinks, name) - } - sort.Strings(backlinks) - for _, name := range backlinks { - e.Backlinks = - append(e.Backlinks, template.HTML(makeLink(&entries, name))) - } +func writeEntry(e *Entry, t *template.Template, + entries *map[string]*Entry) error { + f, err := os.Create(e.PathDestination) + if err != nil { + return err + } - if err = t.Execute(f, e); err != nil { - log.Fatalln(err) - } + backlinks := []string{} + for name := range e.backlinks { + backlinks = append(backlinks, name) } + sort.Strings(backlinks) + for _, name := range backlinks { + e.Backlinks = + append(e.Backlinks, template.HTML(makeLink(entries, name))) + } + + return t.Execute(f, e) +} +func writeIndex(t *template.Template, entries *map[string]*Entry) error { // Reorder entries reversely, primarily by date, secondarily by filename. ordered := []*Entry{} - for _, e := range entries { + for _, e := range *entries { ordered = append(ordered, e) } @@ -322,15 +304,62 @@ func main() { return p2.Before(*p1) }) - // Execute a template from the standard input. + // TODO(p): Splitting content to categories would be nice. + return t.Execute(os.Stdout, ordered) +} + +func singleFile() { + html, meta, err := Render(os.Stdin, configuration.NewConfiguration()) + if err != nil { + log.Println(err) + } else if meta.Title != "" { + _, _ = os.Stdout.WriteString("<h1>") + _ = xml.EscapeText(os.Stdout, []byte(meta.Title)) + _, _ = os.Stdout.WriteString("</h1>\n") + } + _, _ = io.Copy(os.Stdout, html) +} + +func main() { + if len(os.Args) < 2 { + singleFile() + return + } + if len(os.Args) < 3 { + log.Fatalf("usage: %s TEMPLATE GLOB...\n", os.Args[0]) + } + + // Read the common page header. + header, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + log.Fatalln(err) + } + t, err := template.New("page").Parse(string(header)) + if err != nil { + log.Fatalln(err) + } + + // Process all entries. + entries, err := loadEntries(os.Args[2:]) + if err != nil { + log.Fatalln(err) + } + for _, e := range entries { + if err := writeEntry(e, t, &entries); err != nil { + log.Fatalln(err) + } + } + + // Read a template from the standard input, write an index. var input []byte if input, err = ioutil.ReadAll(os.Stdin); err != nil { log.Fatalln(err) } - - // TODO(p): Splitting content to categories would be nice. t, err = template.New("-").Parse(string(input)) - if err = t.Execute(os.Stdout, ordered); err != nil { + if err != nil { + log.Fatalln(err) + } + if err := writeIndex(t, &entries); err != nil { log.Fatalln(err) } } |