// Package gempub implements the gempub 1.0.0 specification as described here: https://codeberg.org/oppenlab/gempub package gempub import ( "bufio" "errors" "fmt" "io" "strings" "time" ) type Metadata struct { Title string // mandatory title of the work GpubVersion string // mandatory Gempub format version: 1.0.0 Index string // path to index.gmi, if none is specified it should be assumed to be in the root Author string // author of the work Language string // BCP 47 language code Charset string // if not set, assume UTF-8 Description string // human-readable description Published time.Time // YYYY when date is unknown PublishDate time.Time // YYYY-MM-DD eg. 2006-01-02 RevisionDate time.Time // YYYY-MM-DD eg. 2006-01-02 Copyright string // copyright of the book License string // license of the book Version string a // human readable only, not meant to be parsed Cover string // a JPG or PNG image which can be anywhere in the directory structure } var ( ErrNoTitle = errors.New("gempub: no title in document") ) func loadDateOrYear(when string) (t time.Time, err error) { if len(when) == 4 { t, err = time.Parse("2006", when) return } t, err = time.Parse("2006-01-02", when) return } func (m Metadata) Valid() error { switch { case m.Title == "": return ErrNoTitle case m.GpubVersion != "1.0.0": return fmt.Errorf("gempub: wrong gempub version: %v", m.GpubVersion) } return nil } func ReadMetadata(r io.Reader) (*Metadata, error) { var result Metadata sc := bufio.NewScanner(r) for sc.Scan() { line := sc.Text() sp := strings.SplitN(line, ":", 2) key, val := sp[0], sp[1] val = strings.TrimSpace(val) switch key { case "title": result.Title = val case "gpubVersion": result.GpubVersion = val case "index": result.Index = val case "author": result.Author = val case "language": result.Language = val case "charset": result.Charset = val case "description": result.Description = val case "published": when, err := loadDateOrYear(val) if err != nil { return nil, fmt.Errorf("gempub: can't understand date %q: %v", val, err) } result.Published = when case "publishDate": when, err := loadDateOrYear(val) if err != nil { return nil, fmt.Errorf("gempub: can't understand date %q: %v", val, err) } result.PublishDate = when case "revisionDate": when, err := loadDateOrYear(val) if err != nil { return nil, fmt.Errorf("gempub: can't understand date %q: %v", val, err) } result.RevisionDate = when case "copyright": result.Copyright = val case "license": result.License = val case "cover": result.Cover = val } } return &result, result.Valid() }