mela

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2023 License: MIT Imports: 19 Imported by: 0

README

Mela recipes

An opinionated library for stream-parsing Mela's recipe files.

Includes customisations that define a convention for the ID of recipes derrived from books. See ISBN extension for examples.

Usage

// import github.com/jphastings/mela-recipes

The simple Open function is quickest for interacting with .melarecipe and .melarecipes files:

recipes, err := mela.Open("fixtures/a+b.melarecipes")
if err != nil {
  log.Fatalf("A filesystem error: %v\n", err)
}

for i, r := range recipes {
  fmt.Printf("Recipe #%d title: %s\n", i, r.Title)
}

// Output:
// Recipe #0 title: B title
// Recipe #1 title: A title

Note: the order of the recipes is defined on the structure of the underlying zip file, which isn't necessarily alphabetical, or the sort order of the recipes when exported.

ISBNs can be set & parsed with the SetBook and Book methods:

recipes, err := mela.Open("fixtures/a.melarecipe")
if err != nil {
  log.Fatalf("A filesystem error: %v\n", err)
}

r := recipes[0]

// Note: Setting the book details creates a new object with a URN based on a standardised form ISBN-13.
setErr := r.SetBook("123456789X", mela.MustParsePages("42"), 2)
if setErr != nil {
  log.Fatalf("Invalid Book details given: %v\n", err)
}

fmt.Println("ID:", r.ID)
fmt.Println("ISBN:", r.Book().ISBN13)
fmt.Println("Page numbers:", r.Book().Pages)
fmt.Println("Recipe number:", r.Book().RecipeNumber)


// Output:
// ID: urn:isbn:9781234567897#pages=42&recipe=2
// ISBN: 9781234567897
// Page numbers: 42
// Recipe number: 2

You can standardize the Recipe file with a call to Stanadrdize(). This performs three stanadrdizations:

  • Pulls an ISBN, page & recipe numbers from the Notes field, if present in the form _9781234512345, p.123-125, 2nd to represent the book with ISBN 9781234512345, optionally on pages 123 to 125, optionally the 2nd recipe on that first page (see ISBN Extension for more). Changes the recipe's ID to reference this book.
  • Converts any images to be maximum 1024x1024px, and in WebP format.
  • For books with an ISBN, retrieves the book title from the OpenLibrary and sets the 'link' field of the recipe to be the title of the book.

Extensions

This library includes backwards-compatible extensions to the Mela file format.

ISBN Extension

For recipes that have been scanned or imported from books, the id field of the recipe can be set to an ISBN URN with optional page and recipe-number-on-page references. This is invisible to users of .melarecipe/.melarecipes files, but provides useful information for cataloguing.

For example, the second recipe on page 42 of the book with ISBN-13 9781234567897 (which would be ISBN-10 123456789X) would have an ID of urn:isbn:9781234567897#pages=42&recipe=1.

Any .melarecipe that has an id which is a URN meeting the RFC-3187 spec will be interpreted as having come from a book.

If that URN includes a valid pages f-component (see RFC-8141§2.3), then the recipe will be interpreted as being imported from from the page or pages labelled with the specific page numbers.

If the URN also includes a valid recipe f-component, then the recipe will be interpreted as coming from the Nth recipe on the first page referenced in pages. 0 represents "not explicitly specified, presumed the first recipe", 1 explicitly declares this recipe as the first one on the page, 2 explicitly as the second and so on. (Neatly resolving the awkward difference between humans and machines on zero-indexing).

Examples
  • The first recipe on a single page: #pages=42 or, explicitly, #pages=42&recipe=1
  • The second recipe on a single page: #pages=42&recipe=2
  • (The first recipe on) a range of contiguous pages: #pages=42-45
  • (The first recipe on) a set of non-contiguous pages: #pages=42,44,46-49
  • (The first recipe on) a set of pages that use non-numeric numbering: #pages=v-vii,x-xii
  • (The first recipe on) a page with a number that uses hyphens: #pages=3%2D2

The pages referenced should be listed in the order they appear in the book. For example, #pages=42-41 and #pages=42,41 would both be incorrect unless the page labelled "41" comes immediately after the page labelled "42" in the direction the book is read).

ABNF notation
pages_f     = contig *( "," contig )
contig      = page-num [ "-" page-num ]
page-num    = 1*( ALPHA / DIGIT / pct-encoded )
pct-encoded = "%" HEXDIG HEXDIG

recipe_f    = 1*DIGIT

(Using RFC5234 syntax.)

Documentation

Index

Constants

View Source
const ZipFileMagicBytes = "PK\x03\x04"

Variables

View Source
var ErrIncorrectISBN10 = errors.New("the given ISBN-10 has an incorrect digit")
View Source
var ErrIncorrectISBN13 = errors.New("the given ISBN-13 has an incorrect digit")
View Source
var ErrInvalidISBN = errors.New("the given string does not have the right number of characters to be an ISBN")
View Source
var ErrInvalidISBN10 = errors.New("the given string has 10 digits, but is not a valid ISBN-10")
View Source
var ErrInvalidISBN13 = errors.New("the given string has 13 digits, but is not a valid ISBN-13")
View Source
var ErrInvalidMelaFile = errors.New("given file is neither a melarecipe nor a melarecipes file")
View Source
var ErrInvalidMelaRecipeFile = errors.New("given file is not a melarecipe file")
View Source
var ErrInvalidMelaRecipesFile = errors.New("given file is not a melarecipes file")

Functions

func ParseRecipes

func ParseRecipes(r io.ReaderAt, size int64, onRecipe func(*Recipe, error)) error

ParseRecipe parses a known .melarecipes collection file into a stream of Recipe-compatible structs, calling the onRecipe func for each, as it is parsed

Types

type B64Image added in v0.0.2

type B64Image []byte

func (B64Image) Optimize added in v0.0.2

func (i B64Image) Optimize() (B64Image, error)

func (B64Image) OptimizeWithConfig added in v0.0.2

func (i B64Image) OptimizeWithConfig(maxWidth, maxHeight int) (B64Image, error)

type Book

type Book struct {
	ISBN13       string
	Pages        Pages
	RecipeNumber uint
}

type MaybeDuration

type MaybeDuration string

func (MaybeDuration) Parse

func (m MaybeDuration) Parse() (*time.Duration, error)

type PageRange

type PageRange []string

type Pages

type Pages []PageRange

func MustParsePages

func MustParsePages(str string) Pages

func ParsePages

func ParsePages(pages string) (Pages, error)

func (Pages) String

func (p Pages) String() string

type PeopleCount

type PeopleCount string

func (PeopleCount) Parse

func (pc PeopleCount) Parse() (uint64, error)

type Recipe

type Recipe struct {
	Filename     string            `json:"-"`
	ID           string            `json:"id"`
	Title        string            `json:"title"`
	Link         string            `json:"link"`
	Text         string            `json:"text"`
	Ingredients  SectionedSequence `json:"ingredients"`
	Instructions SectionedSequence `json:"instructions"`
	Nutrition    string            `json:"nutrition"`
	Categories   []string          `json:"categories"`
	Notes        string            `json:"notes"`

	Images    []B64Image    `json:"images"`
	Yield     PeopleCount   `json:"yield"`
	PrepTime  MaybeDuration `json:"prepTime"`
	CookTime  MaybeDuration `json:"cookTime"`
	TotalTime MaybeDuration `json:"totalTime"`
}

func Open

func Open(filename string) ([]*Recipe, error)

Open is a smart, file-system based function for opening a .melarecipe or .melarecipes file from disk. For simplicity's sake, it will silently ignore any invalid recipes within a .melarecipes file, use ParseRecipes for greater control.

func ParseRecipe

func ParseRecipe(r io.Reader) (*Recipe, error)

ParseRecipe parses a known single .melarecipe file into a Recipe-compatible struct

func (*Recipe) Book

func (r *Recipe) Book() *Book

func (*Recipe) Save

func (r *Recipe) Save(dir string) (string, error)

func (*Recipe) SetBook

func (r *Recipe) SetBook(isbn10or13 string, pages Pages, recipeNumber uint) error

func (*Recipe) Standardize

func (r *Recipe) Standardize(network bool) error

type SectionedSequence

type SectionedSequence string

func (SectionedSequence) Parse

func (ss SectionedSequence) Parse() map[string][]string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL