package gemtext import ( "bytes" "html/template" "net/url" "regexp" "strconv" "strings" "time" ) type gemSub struct { ID template.URL Title string Subtitle string Updated string Entries []gemSubEntry } type gemSubEntry struct { ID template.URL Updated string Title string } var linkElemRE = regexp.MustCompile(`(\d{4})-([0-1]\d)-([0-3]\d)`) func parseGemSub(doc Document, location *url.URL) *gemSub { sub := &gemSub{ID: template.URL(location.String())} updated := time.Time{} for i, line := range doc { switch line.Type() { case LineTypeHeading1: if sub.Title != "" { continue } sub.Title = line.(HeadingLine).Body() for { // skip any empty lines i += 1 if i >= len(doc) || strings.TrimPrefix(doc[i].String(), "\r") != "\n" { break } } if i < len(doc) && doc[i].Type() == LineTypeHeading2 { sub.Subtitle = doc[i].(HeadingLine).Body() } case LineTypeLink: label := line.(LinkLine).Label() if len(label) < 10 { continue } match := linkElemRE.FindStringSubmatch(label[:10]) if match == nil { continue } year, err := strconv.Atoi(match[1]) if err != nil { continue } month, err := strconv.Atoi(match[2]) if err != nil || month > 12 { continue } day, err := strconv.Atoi(match[3]) if err != nil || day > 31 { continue } entryUpdated := time.Date(year, time.Month(month), day, 12, 0, 0, 0, time.UTC) entryTitle := strings.TrimLeft(strings.TrimPrefix(strings.TrimLeft(label[10:], " \t"), "-"), " \t") sub.Entries = append(sub.Entries, gemSubEntry{ ID: template.URL(line.(LinkLine).URL()), Updated: entryUpdated.Format(time.RFC3339), Title: entryTitle, }) if entryUpdated.After(updated) { updated = entryUpdated sub.Updated = updated.Format(time.RFC3339) } } } return sub } func GemsubToAtom(doc Document, location url.URL) string { buf := &bytes.Buffer{} if err := atomTmpl.Execute(buf, parseGemSub(doc, &location)); err != nil { panic(err) } return `` + "\n" + buf.String() } var atomTmpl = template.Must(template.New("atom").Parse(` {{.ID}} {{.Title}} {{- if .Subtitle }} {{.Subtitle}} {{- end }} {{.Updated}} {{- range .Entries }} {{.ID}} {{.Title}} {{.Updated}} {{- end }} `[1:]))