178 lines
4.2 KiB
Go
178 lines
4.2 KiB
Go
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 // human readable only, not meant to be parsed
|
|
Cover string // a JPG or PNG image which can be anywhere in the directory structure
|
|
}
|
|
|
|
func (m Metadata) Write(w io.Writer) error {
|
|
if err := m.Valid(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := fmt.Fprintln(w, "title: ", m.Title); err != nil {
|
|
return err
|
|
}
|
|
if _, err := fmt.Fprintln(w, "gpubVersion: ", m.GpubVersion); err != nil {
|
|
return err
|
|
}
|
|
if m.Index != "" {
|
|
if _, err := fmt.Fprintln(w, "index: ", m.Index); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Author != "" {
|
|
if _, err := fmt.Fprintln(w, "author: ", m.Author); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Language != "" {
|
|
if _, err := fmt.Fprintln(w, "language: ", m.Language); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Charset != "" {
|
|
if _, err := fmt.Fprintln(w, "charset: ", m.Charset); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Description != "" {
|
|
if _, err := fmt.Fprintln(w, "description: ", m.Description); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Copyright != "" {
|
|
if _, err := fmt.Fprintln(w, "copyright: ", m.Copyright); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Version != "" {
|
|
if _, err := fmt.Fprintln(w, "version: ", m.Version); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if m.Cover != "" {
|
|
if _, err := fmt.Fprintln(w, "cover: ", m.Cover); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if !m.Published.IsZero() {
|
|
if _, err := fmt.Fprintln(w, "published: ", m.Published.Format("2006-01-02")); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !m.PublishDate.IsZero() {
|
|
if _, err := fmt.Fprintln(w, "publishDate: ", m.PublishDate.Format("2006-01-02")); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !m.RevisionDate.IsZero() {
|
|
if _, err := fmt.Fprintln(w, "revisionDate: ", m.RevisionDate.Format("2006-01-02")); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
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()
|
|
}
|