Documentation
¶
Overview ¶
bookjson.go provides GitBook book.json compatibility for mdPress. It parses a GitBook-style book.json file and converts it to a BookConfig.
Package config loads and validates mdpress configuration. It reads book metadata, chapter definitions, style settings, and output options from book.yaml.
discover.go implements zero-config project discovery. When neither book.yaml nor SUMMARY.md exists, mdpress scans .md files, sorts them, and derives chapter metadata automatically.
natural_sort.go orders file names the way their author numbered them.
Plain lexical order puts "10-deploy.md" and "11-scale.md" ahead of "2-install.md", which silently reorders a book whose chapters are numbered past nine — and neither build nor validate had any way to notice.
summary.go parses chapter structure from SUMMARY.md. SUMMARY.md uses Markdown link lists to define chapter order in a GitBook-compatible format.
Format example:
# Summary * [Preface](preface.md) * [Chapter 1](chapter01/README.md) * [Section 1.1](chapter01/section01.md) * [Chapter 2](chapter02/README.md)
unknown_keys.go reports book.yaml keys that mdpress does not recognize.
The loader is deliberately non-strict — an unknown key must not break a build that used to work, and forward compatibility matters for a config file people copy between versions. But silently discarding a key is the worst possible outcome for the user: they edit book.yaml, rebuild, see no change, and have nothing to debug with. So unknown keys are surfaced as warnings, with a suggestion when a known sibling is close enough to be the intent.
Index ¶
- Constants
- func IsValidPageSize(s string) bool
- func NaturalCompare(a, b string) int
- func NaturalLess(a, b string) bool
- func TitleFromDirName(dir string) string
- func ValidationErrors(err error) []error
- type BookConfig
- type BookMeta
- type ChapterDef
- type CoverMeta
- type DiscoverError
- type HeaderFooterStyle
- type MarginConfig
- type MarkdownConfig
- type OutputConfig
- type PluginConfig
- type ReadmeMetadata
- type StyleConfig
- type UnknownKey
Constants ¶
const DefaultBookTitle = "Untitled Book"
DefaultBookTitle is the placeholder used when book.title is unset. It is exported so callers can tell "the user named their book" from "nothing took effect" — reporting the placeholder as a valid title hid typo'd config keys.
Variables ¶
This section is empty.
Functions ¶
func IsValidPageSize ¶ added in v0.7.0
IsValidPageSize reports whether s is a recognized page size name (case-insensitive).
func NaturalCompare ¶ added in v0.8.0
NaturalCompare compares a and b treating runs of digits as numbers, so "2-install" sorts before "10-deploy". It returns a negative number when a sorts first, zero when the two are equivalent, and a positive number otherwise, matching the contract of cmp.Compare.
func NaturalLess ¶ added in v0.8.0
NaturalLess reports whether a sorts before b in natural order.
func TitleFromDirName ¶ added in v0.8.0
TitleFromDirName turns a project directory path into a readable book title, e.g. "/src/my-docs" → "My docs". It is exported so that `mdpress init` picks the same title as zero-config discovery for the same directory — the two used to disagree, and so did the artifact names derived from them.
func ValidationErrors ¶ added in v0.8.0
ValidationErrors flattens an error returned by BookConfig.Validate (or a wrapper around one) into the individual problems it reports, so a caller can render one line per problem instead of a single blob of joined text. A nil error yields nil; an error that is not a join yields a one-element slice.
Types ¶
type BookConfig ¶
type BookConfig struct {
Book BookMeta `yaml:"book"`
Chapters []ChapterDef `yaml:"chapters"`
Style StyleConfig `yaml:"style"`
Output OutputConfig `yaml:"output"`
Markdown MarkdownConfig `yaml:"markdown"`
// Plugins lists the plugins to run during the build, in declaration order.
Plugins []PluginConfig `yaml:"plugins"`
// Variables are user-defined template variables, usable in Markdown as
// {{ key }} alongside the built-in book.*/style.*/output.* values.
Variables map[string]string `yaml:"variables"`
// These fields are auto-detected by Load instead of being set directly in YAML.
GlossaryFile string `yaml:"-"` // Path to GLOSSARY.md, if present.
LangsFile string `yaml:"-"` // Path to LANGS.md, if present.
// contains filtered or unexported fields
}
BookConfig is the top-level configuration for a book.
func DefaultConfig ¶
func DefaultConfig() *BookConfig
DefaultConfig returns a config populated with reasonable defaults.
func Discover ¶
func Discover(ctx context.Context, dir string) (*BookConfig, error)
Discover auto-discovers project configuration in a directory. Priority: book.yaml > book.json (GitBook compat) > SUMMARY.md > Markdown file scanning. The context is used for potentially long-running operations like git commands.
func Load ¶
func Load(path string) (*BookConfig, error)
Load reads a config file from disk. If chapters are empty, it attempts to load them from SUMMARY.md in the same directory. It also auto-detects GLOSSARY.md and LANGS.md.
func LoadBookJSON ¶ added in v0.3.1
func LoadBookJSON(ctx context.Context, path string) (*BookConfig, error)
LoadBookJSON reads a GitBook book.json file and returns an equivalent BookConfig.
Metadata fields (title, author, description, language, plugins) are loaded from book.json. Chapter definitions are NOT loaded here; instead, Discover() handles chapters via SUMMARY.md or auto-discovery, which allows proper priority orchestration of configuration sources. The context is used for potentially long-running operations like git commands.
func (*BookConfig) AllowRawHTML ¶ added in v0.8.0
func (c *BookConfig) AllowRawHTML() bool
AllowRawHTML reports whether raw HTML embedded in Markdown should be rendered as HTML rather than escaped.
mdpress treats Markdown sources as trusted input — they come from the same repository as book.yaml — so this defaults to true and raw HTML passes through unfiltered, including <script> and <iframe>. A project that renders Markdown it did not write (community contributions, user submissions) should set `markdown.allow_html: false`.
func (*BookConfig) BaseDir ¶
func (c *BookConfig) BaseDir() string
BaseDir returns the directory containing the config file.
func (*BookConfig) ResolvePath ¶
func (c *BookConfig) ResolvePath(p string) string
ResolvePath resolves a path relative to the config directory.
Security: This function does NOT verify that the result is contained within the project directory. It is the caller's responsibility to ensure the input path has been validated (e.g. via utils.SafeJoin or BookConfig.Validate) before passing it here. Absolute paths are returned unchanged, so an attacker-controlled absolute path could escape the project root.
func (*BookConfig) SetBaseDir ¶
func (c *BookConfig) SetBaseDir(dir string)
SetBaseDir overrides the base directory used to resolve relative paths. It is primarily useful for tests and for constructing configs in memory.
func (*BookConfig) Validate ¶
func (c *BookConfig) Validate() error
Validate checks the configuration for completeness and validity.
It reports every independent problem it finds rather than stopping at the first one: a book.yaml with five mistakes used to take five edit-and-rerun cycles to clean up. The result is an errors.Join value, so callers that want to render one line per problem can unwrap it with ValidationErrors.
type BookMeta ¶
type BookMeta struct {
Title string `yaml:"title"`
Subtitle string `yaml:"subtitle"`
Author string `yaml:"author"`
Version string `yaml:"version"`
Language string `yaml:"language"`
Description string `yaml:"description"`
Cover CoverMeta `yaml:"cover"`
// Favicon is the site icon: a project-relative image path, or an absolute
// URL. Empty keeps mdpress's built-in book emoji.
Favicon string `yaml:"favicon"`
// Logo is an image shown above the title in the site sidebar: a
// project-relative image path, or an absolute URL. Empty shows no logo.
Logo string `yaml:"logo"`
// Copyright is a short notice rendered in each page's footer, e.g.
// "© 2026 Acme Inc.". Empty renders no notice.
Copyright string `yaml:"copyright"`
}
BookMeta contains book metadata.
type ChapterDef ¶
type ChapterDef struct {
Title string `yaml:"title"`
File string `yaml:"file"`
// Section is an optional group label rendered above this chapter in the
// site sidebar, starting a new group. SUMMARY.md "## Heading" lines set it
// on the chapter that follows them; book.yaml can set it directly. It is
// carried on a real chapter rather than modeled as a file-less entry, so
// nothing downstream has to cope with a chapter that has no content.
Section string `yaml:"section"`
Sections []ChapterDef `yaml:"sections"`
}
ChapterDef defines a chapter and its nested sections.
func FlattenChapters ¶
func FlattenChapters(chapters []ChapterDef) []ChapterDef
FlattenChapters expands nested chapter definitions into a flat list. This is the canonical implementation; callers should use this instead of maintaining their own flattening logic.
func ParseSummary ¶
func ParseSummary(path string) ([]ChapterDef, error)
ParseSummary parses chapter definitions from SUMMARY.md. Nesting is expressed with indentation: two spaces or one tab per level.
type CoverMeta ¶
type CoverMeta struct {
Image string `yaml:"image"`
Background string `yaml:"background"` // Background color, for example "#1a1a2e".
}
CoverMeta stores cover configuration.
type DiscoverError ¶
DiscoverError describes auto-discovery failures.
func (*DiscoverError) Error ¶
func (e *DiscoverError) Error() string
type HeaderFooterStyle ¶
type HeaderFooterStyle struct {
}
HeaderFooterStyle stores header and footer text templates.
type MarginConfig ¶
type MarginConfig struct {
Top float64 `yaml:"top"`
Bottom float64 `yaml:"bottom"`
Left float64 `yaml:"left"`
Right float64 `yaml:"right"`
}
MarginConfig stores page margins in millimeters.
type MarkdownConfig ¶ added in v0.8.0
type MarkdownConfig struct {
// AllowHTML controls whether raw HTML written in Markdown reaches the
// output. A nil pointer means "not configured" and keeps the default.
AllowHTML *bool `yaml:"allow_html"`
}
MarkdownConfig controls how Markdown sources are parsed.
type OutputConfig ¶
type OutputConfig struct {
Filename string `yaml:"filename"`
TOC bool `yaml:"toc"`
TOCMaxDepth int `yaml:"toc_max_depth"` // Maximum heading level to include in TOC (1-6, default 2). Level 1 = h1 only, 2 = h1+h2, etc.
Cover bool `yaml:"cover"`
Header bool `yaml:"header"`
Formats []string `yaml:"formats"` // Output formats: pdf, html, epub, site (default ["pdf"]).
PDFTimeout int `yaml:"pdf_timeout"` // PDF generation timeout in seconds (default 120).
Watermark string `yaml:"watermark"` // Watermark text (e.g., "DRAFT", "CONFIDENTIAL")
WatermarkOpacity float64 `yaml:"watermark_opacity"` // Opacity 0.0-1.0 (default 0.1)
MarginTop string `yaml:"margin_top"` // e.g., "20mm"; unset means style.margin.top
MarginBottom string `yaml:"margin_bottom"` // e.g., "20mm"; unset means style.margin.bottom
MarginLeft string `yaml:"margin_left"` // e.g., "25mm"; unset means style.margin.left
MarginRight string `yaml:"margin_right"` // e.g., "25mm"; unset means style.margin.right
GenerateBookmarks bool `yaml:"generate_bookmarks"` // Generate PDF bookmarks from headings (default true)
SiteURL string `yaml:"site_url"` // Public base URL of the deployed site (e.g. https://user.github.io/repo); enables sitemap.xml
EditBase string `yaml:"edit_base"` // Base URL for "edit this page" links (e.g. https://github.com/user/repo/edit/main/)
TaggedPDF *bool `yaml:"tagged_pdf"` // Generate accessible tagged PDF (default true; false produces smaller files)
// A nil pointer means "not configured" and keeps the default; an explicit
// empty string removes the line. It is a pointer for exactly that reason —
// a plain string cannot tell "unset" from "the user wants no footer".
// Its value is emitted as raw HTML, on the same trust footing as raw HTML
// in the Markdown sources (see BookConfig.AllowRawHTML).
FooterHTML *string `yaml:"footer_html"`
// ShowThemeBadge renders the theme name as a badge in the site sidebar.
// Off by default: it is mdpress advertising itself on someone else's
// published site, and removing it used to require a CSS hack.
ShowThemeBadge bool `yaml:"show_theme_badge"`
}
OutputConfig stores output-related settings.
type PluginConfig ¶ added in v0.3.0
type PluginConfig struct {
// Name is the unique plugin identifier (lowercase, hyphen-separated).
Name string `yaml:"name"`
// Path is the path to the plugin executable, relative to book.yaml.
Path string `yaml:"path"`
// Config contains arbitrary key-value pairs passed to the plugin.
Config map[string]any `yaml:"config"`
}
PluginConfig describes a single plugin entry in book.yaml.
Example:
plugins:
- name: word-count
path: ./plugins/word-count
config:
warn_threshold: 500
type ReadmeMetadata ¶ added in v0.3.1
type ReadmeMetadata struct {
Title string // Book title (may differ from H1 heading).
Version string // e.g. "1.6.5"
Author string // Detected author name or GitHub username.
Language string // e.g. "zh-CN", "en-US"
}
ReadmeMetadata holds metadata extracted from a project README.md.
func ExtractReadmeMetadata ¶ added in v0.3.1
func ExtractReadmeMetadata(ctx context.Context, path string) ReadmeMetadata
ExtractReadmeMetadata reads a README.md and extracts book metadata. It tries to find a meaningful title (beyond just the H1), version, language, and author. Exported so that cmd/init_cmd.go can also use it. The context is used for potentially long-running operations like git commands.
type StyleConfig ¶
type StyleConfig struct {
Theme string `yaml:"theme"`
PageSize string `yaml:"page_size"`
FontFamily string `yaml:"font_family"`
FontSize string `yaml:"font_size"`
CodeTheme string `yaml:"code_theme"`
LineHeight float64 `yaml:"line_height"`
Margin MarginConfig `yaml:"margin"`
Header HeaderFooterStyle `yaml:"header"`
CustomCSS string `yaml:"custom_css"`
}
StyleConfig stores style-related settings.
type UnknownKey ¶ added in v0.8.0
type UnknownKey struct {
// Path is the dotted location in the document, e.g. "style.them".
Path string
// Suggestion is the closest known sibling key, or "" if none is close.
Suggestion string
}
UnknownKey is a config key with no corresponding field.
func FindUnknownKeys ¶ added in v0.8.0
func FindUnknownKeys(data []byte) []UnknownKey
FindUnknownKeys parses data as a generic document and walks it against the BookConfig type, collecting keys with no matching field.
func (UnknownKey) Hint ¶ added in v0.8.0
func (u UnknownKey) Hint() string
Hint renders the "did you mean" text for a warning, or a generic note.