Help us shape the future of Go! Take the 2026 Go Developer Survey

book

package
v0.1.14 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 50 Imported by: 0

Documentation

Overview

Package book checks and builds the book deliverable of an lfm project: a researched concept in deliverables/book/concept.md, chapters written one at a time from it, and the finished EPUB and PDF that buyers download from a page at an unlisted path.

The book follows the page's method. Its concept cites the project's research by ID, its chapters are checked for structure, length and the stock phrases of generated prose, and it is only built once every chapter exists. Until then the download page tells buyers that their copy is being written.

Index

Constants

View Source
const (
	Dir         = "deliverables/book"
	ConceptFile = Dir + "/concept.md"
	ChaptersDir = "chapters"
	ImagesDir   = "images"
	StyleFile   = "book.css"
)

Layout of the deliverable inside a project.

View Source
const (
	MinChapters   = 3
	MinObjections = 3
	MinVoices     = 8 // distinct voices cited
	MinPeers      = 3 // distinct competing books or guides cited
	MinJobWords   = 4
	MinWords      = 300
	MaxWords      = 20000
	WordTolerance = 0.35 // a chapter may run this far over or under its target
	CoverWidth    = 1600
	CoverHeight   = 2560
)

Minimums the concept is held to.

View Source
const (
	RuleConfig   = "book.config"
	RuleConcept  = "book.concept"
	RuleEvidence = "book.evidence"
	RuleOpen     = "book.open"
	RuleChapter  = "book.chapter"
	RuleCopy     = "book.copy"
	RuleValue    = "book.value"
	RuleMachine  = "book.machine"
	RuleImages   = "book.images"
	RuleDelivery = "book.delivery"
	RuleBuild    = "book.build"
	RuleLayout   = "book.layout"
	RuleFonts    = "book.fonts"
	RulePDF      = "book.pdf"
	RuleListing  = "book.listing"
	RuleChannels = "book.channels"
)

Rule IDs.

View Source
const (
	MaxDescription   = 4000 // KDP, counted as the HTML it receives
	MinDescription   = 200
	MaxShort         = 300
	MaxBackCover     = 1200
	MaxKeywords      = 7 // KDP
	MaxKeywordLength = 50
	MaxTags          = 13 // Etsy
	MaxTagLength     = 20
	MaxCategories    = 3
	MaxTitleLength   = 200 // KDP, title and subtitle together
)

Store limits the listing is held to; the strictest channel sets each one.

View Source
const Bleed = 0.125

Bleed is the margin beyond the trim that print covers extend into.

View Source
const ListingFile = Dir + "/listing.md"

ListingFile holds the store texts of the book: descriptions, keywords, categories, prices and the AI disclosure, written once and rendered into the format and limits of every channel.

View Source
const MaxCoverBytes = 5 << 20

MaxCoverBytes is the largest store cover KDP takes.

Variables

View Source
var (
	ChapterColumns = []string{"#", "Title", "Job", "Beats", "Words", "File"}
	ImageColumns   = []string{"Image", "Chapter", "Job", "Art direction", "File"}
)

Columns of the tables.

View Source
var FictionSections = []concept.SectionSpec{
	{Name: "Reader"}, {Name: "Premise"}, {Name: "Cast"}, {Name: "World"},
	{Name: "Arc"}, {Name: "Hooks"}, {Name: "Voice"}, {Name: "Chapters"},
	{Name: "Matter", Optional: true}, {Name: "Imagery"}, {Name: "Look"},
	{Name: "Qualities", Optional: true}, {Name: "Changelog", Optional: true},
}

FictionSections describe a story plan.

View Source
var KDPTrims = map[string]bool{"5x8in": true, "5.5x8.5in": true, "6x9in": true, "A4": true, "letter": true}

KDPTrims are the paperback trims KDP prints, of those lfm offers.

View Source
var ListingSections = []concept.SectionSpec{
	{Name: "Description"},
	{Name: "Short description"},
	{Name: "Back cover"},
	{Name: "Author"},
	{Name: "Keywords"},
	{Name: "Tags"},
	{Name: "Categories"},
	{Name: "Prices"},
	{Name: "AI"},
}

ListingSections are the sections of listing.md in their required order.

View Source
var Sections = []concept.SectionSpec{
	{Name: "Reader"},
	{Name: "Promise"},
	{Name: "Big idea"},
	{Name: "Objections"},
	{Name: "Hooks"},
	{Name: "Voice"},
	{Name: "Devices"},
	{Name: "Cases", Optional: true},
	{Name: "Chapters"},
	{Name: "Matter", Optional: true},
	{Name: "Imagery"},
	{Name: "Look"},
	{Name: "Qualities", Optional: true},
	{Name: "Changelog", Optional: true},
}

Sections of the book concept in their required order. The format follows what makes a useful nonfiction book: a scope (reader, promise, who it is not for, what it will not cover), one idea the market lacks, hooks, a voice with exact phrases, recurring devices, and chapters that each have one job.

View Source
var Trims = map[string][2]float64{
	"5x8in":     {5, 8},
	"5.5x8.5in": {5.5, 8.5},
	"6x9in":     {6, 9},
	"A5":        {5.83, 8.27},
	"A4":        {8.27, 11.69},
	"letter":    {8.5, 11},
}

Trims are the page formats the PDF can be printed in, with their size in inches.

Functions

func Channels

func Channels() []string

Channels returns the keys of the channels lfm prepares, in order.

func Distribution

func Distribution(r Report, b Built, p Printed, day string) (map[string][]byte, []string, []diagnostic.Diagnostic)

Distribution assembles the store packages: every file once at the top, a guide per channel in stores/ naming the files it takes and every field in its format, and a README over all of them. Channels that refuse the book are listed in the README only.

func DownloadPage

func DownloadPage(plan Plan, cfg Config, files []deliver.File) []byte

DownloadPage renders the unlisted page buyers land on after paying. With no files the book is still being written, and the page says so.

func Gutter

func Gutter(pages int) float64

Gutter is the inside margin of a paperback with pages pages: KDP's minimum gutter for the page count plus a quarter inch, and never below three quarters of an inch, which also meets IngramSpark's half-inch margins.

func KDPDescription

func KDPDescription(md string) string

KDPDescription renders Markdown into the HTML KDP accepts: p, br, b, i, em, h4 to h6, ul, ol and li.

func KDPSpine

func KDPSpine(pages int, paper string) float64

KDPSpine is the spine width of a KDP paperback.

func LuluSpine

func LuluSpine(pages int) float64

LuluSpine is the spine width of a Lulu perfect-bound paperback.

func PlainText

func PlainText(md string) string

PlainText renders Markdown as plain text for stores that take no markup: paragraphs separated by blank lines, list items with bullets.

func Present

func Present(p project.Project) bool

Present reports whether the project has a book.

func PrintDPI

func PrintDPI(pixels [2]int, inches [2]float64) int

PrintDPI is the resolution an image of the given pixels reaches when it fills a print area of the given inches, cropped to cover it.

func Rules

func Rules() []diagnostic.RuleInfo

Rules describes every book rule for the catalog.

func SVGSize added in v0.1.12

func SVGSize(data []byte) (float64, float64, error)

SVGSize validates a self-contained SVG and returns its intrinsic dimensions.

func StoreCover

func StoreCover(src, previous []byte) ([]byte, error)

StoreCover returns the cover as the RGB JPEG every store accepts: the source itself when it already is one under 5 MB, otherwise re-encoded. A re-encoded cover carries the hash of its source in a comment, so the cover published last time is reused while the source is unchanged: re-encoding takes a tenth of a second.

func ValidISBN

func ValidISBN(s string) bool

ValidISBN reports whether s is an ISBN-13 with a correct check digit; hyphens and spaces are ignored.

func WrapFile

func WrapFile(key string) string

WrapFile is the file name of the cover wrap laid out with a spine formula.

func Wraps

func Wraps(r Report, pages int) []string

Wraps returns the spine formulas of the cover wraps that a channel taking the paperback of this many pages lays out, so only those are printed.

Types

type Built

type Built struct {
	EPUB        []byte
	Print       []byte            // one HTML document for printing the PDF
	PrintAssets map[string][]byte // flat file names the print documents reference
	TrimInches  [2]float64
	PrintCover  string // flat name of the image for the printed front cover
	CoverPixels [2]int // its size
	// contains filtered or unexported fields
}

Built is the output of a book build.

func Build

func Build(r Report, read Reader, modified time.Time) (Built, error)

Build renders the finished book. modified is the newest change of its sources.

func (Built) ChapterStarts

func (b Built) ChapterStarts(pdf []byte) map[int]int

ChapterStarts maps chapter numbers to the pages they start on, read from the outline of a PDF printed from Document: the chapters are its last top-level bookmarks. It returns nil when the outline does not fit.

func (Built) CoverDocument

func (b Built) CoverDocument(spine float64, spineText bool) []byte

CoverDocument renders the full wrap of the paperback cover: back, spine and front side by side with bleed on every edge. The spine carries title and author when spineText is set; the back carries the listing's back cover text and, with a paperback ISBN, its barcode.

func (Built) Document

func (b Built) Document(o PrintOptions) []byte

Document renders a print document: the downloadable PDF with zero options.

func (Built) Recto

func (b Built) Recto(starts map[int]int) (blanks map[int]bool, pages map[int]int)

Recto plans the blank pages that make every chapter start on a right-hand page, from where the chapters start without them, and the page each then starts on.

type Chapter

type Chapter struct {
	Status string `json:"status"`
	N      int    `json:"n"`
	Title  string `json:"title"`
	Job    string `json:"job"`
	Beats  string `json:"-"`
	Words  int    `json:"words"`
	File   string `json:"file"` // relative to the book folder, e.g. chapters/01-start.md
	Line   int    `json:"-"`
	Exists bool   `json:"written"`
}

Chapter is one planned chapter.

type Config

type Config struct {
	Kind          string   `json:"kind"`
	Author        string   `json:"author"`
	Language      string   `json:"language"`
	Path          string   `json:"path"`
	Offer         string   `json:"offer"`
	Formats       []string `json:"formats"`
	Publisher     string   `json:"publisher"` // seller.name
	Imprint       string   `json:"imprint"`   // seller.imprint
	Paper         string   `json:"paper"`
	ISBNEbook     string   `json:"isbnEbook"`
	ISBNPaperback string   `json:"isbnPaperback"`
	Sell          string   `json:"sell"` // page (default), shops or bundle
}

Config is deliverables.book in lfm.json.

func (Config) Wants

func (c Config) Wants(format string) bool

Wants reports whether format is configured.

type Image

type Image struct {
	Open                                bool
	Name, Chapter, Job, Direction, File string
	Line                                int
}

Image is one planned image.

type Listing

type Listing struct {
	Present     bool
	Description string // Markdown
	Short       string
	BackCover   string
	Author      string
	Keywords    []string
	Tags        []string
	BISAC       []string // "CODE label"
	Thema       []string
	KDP         []string
	Ebook       []Price
	Paperback   []Price
	AIText      string
	AIImages    string
	AITools     string
	AIStatement string
}

Listing is the parsed listing.md.

func (Listing) AIGenerated

func (l Listing) AIGenerated() bool

AIGenerated reports whether any part of the book is AI-generated.

func (Listing) AIUsed

func (l Listing) AIUsed() bool

AIUsed reports whether the book declares any AI use.

type Matter added in v0.1.12

type Matter struct {
	Part, Place, File string
	Line              int
	Exists            bool
}

Matter is one unnumbered front or back part.

type Objection

type Objection struct {
	Text    string
	Chapter int
	Line    int
}

Objection is a reader's doubt and the chapter that answers it.

type Plan

type Plan struct {
	Kind        string
	Cast        []string
	POV, Tense  string
	Matter      []Matter
	CoverOpen   bool
	Name        string // working name from the title line
	Title       string
	Subtitle    string
	Chapters    []Chapter
	Images      []Image
	Cover       string // book-relative path of the cover image
	Trim        string
	Body        string // font stack
	Headings    string
	Accent      string
	Use, Avoid  []string
	UseLines    []int  // the concept line of each Use phrase
	Text        string // the concept as written, for names it declares
	Objections  []Objection
	LookLine    int
	Description string // the promise, as the EPUB description
}

Plan is what the concept decided, as the compiler uses it.

type Price

type Price = deliver.Price

Price is one list price of an edition.

func PriceIn

func PriceIn(prices []Price, currency string) *Price

PriceIn returns the price of an edition in a currency.

type PrintOptions

type PrintOptions struct {
	Paper  bool         // the paperback interior: no cover and no links, mirrored margins
	Inside float64      // inside margin of the paperback in inches
	Pages  map[int]int  // chapter number -> page, printed in the contents
	Blanks map[int]bool // chapter number -> a blank page comes before it
	PadEnd int          // blank pages at the end
}

PrintOptions shape a print document beyond the downloadable PDF.

type Printed

type Printed struct {
	PDF           []byte            // the downloadable PDF, with bookmarks and links
	Interior      []byte            // the paperback interior
	InteriorPages int               // its page count, even
	Inside        float64           // its inside margin in inches
	Wraps         map[string][]byte // full cover wraps by spine formula: "kdp", "lulu"
	Spines        map[string]float64
	Problems      []string // what could not be printed, and why
	Pending       bool     // the book changed since the last release printed it
	LastCover     []byte   // the store cover of the last publish, reused when its source is unchanged
}

Printed holds what Chrome printed for the store packages.

type Reader

type Reader func(rel string) ([]byte, error)

Reader reads a file of the book folder by its book-relative path.

type Report

type Report struct {
	Diagnostics []diagnostic.Diagnostic
	Summary     Summary
	Plan        Plan
	Config      Config
	Sources     map[string][]byte // book-relative path -> bytes of every chapter, image and style read
	Listing     Listing
	EPUBImages  map[string][]byte // optional PNG renditions, keyed by original SVG path
	Previewable bool
	Buildable   bool // config valid and every chapter written; the build may run
}

Report is the result of checking the book.

func Check

func Check(p project.Project, cfg Config, configured bool, offers map[string]*Price, site string, voices *research.Voices, competitors *research.Competitors) Report

Check reads the book of the project. configured tells whether lfm.json has deliverables.book; site is the page URL the download path hangs off.

type SourceError added in v0.1.12

type SourceError struct {
	File string
	Line int
	Err  error
}

SourceError locates a build failure in the author's input.

func (*SourceError) Error added in v0.1.12

func (e *SourceError) Error() string

func (*SourceError) Unwrap added in v0.1.12

func (e *SourceError) Unwrap() error

type Summary

type Summary struct {
	Kind     string         `json:"kind"`
	Blocker  string         `json:"blocker,omitempty"`
	Preview  string         `json:"preview,omitempty"`
	Concept  bool           `json:"concept"`
	Title    string         `json:"name,omitempty"`
	Chapters []Chapter      `json:"chapters,omitempty"`
	Planned  int            `json:"planned"`
	Written  int            `json:"written"`
	Words    int            `json:"words"`
	Target   int            `json:"targetWords"`
	Complete bool           `json:"complete"`
	URL      string         `json:"url,omitempty"`
	Sizes    map[string]int `json:"fileBytes,omitempty"`
	Files    []string       `json:"files,omitempty"` // built formats, set by the build
	Listing  bool           `json:"listing"`
	Pending  bool           `json:"pending"`            // the paperback waits for a release to print
	Layout   string         `json:"layout,omitempty"`   // release: "fits", or the number of layout findings
	Channels []string       `json:"channels,omitempty"` // store packages written to distribution/
	Sell     string         `json:"sell"`               // page, shops or bundle
}

Summary describes the book for the report, the next step and --json.

func (Summary) Next

func (s Summary) Next() *Chapter

Next returns the first unwritten active chapter, then the first planned chapter.

type Wording

type Wording struct {
	Contents, Rights, CoverOf, Start, Copyright, Chapter string
	DownloadTitle, Thanks, Writing, Download, Keep       string
	EPUBNote, PDFNote                                    string
	Accessible                                           string // the EPUB's accessibility summary
}

Wording holds the few texts lfm writes into a book and its download page, per language; English is the fallback.

func Words

func Words(language string) Wording

Words returns the texts lfm writes for a language.

Jump to

Keyboard shortcuts

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