// rPubs Book Template — main entry point // Reads structured content from JSON and renders a complete pocket book. // Works with any format file (A6, A7, digest, etc.) #import "../lib/series-style.typ": apply-series-style, series-colors, series-fonts, series-rule, series-separator #let data = json(sys.inputs.at("data-path")) // Apply series typography #show: apply-series-style // --- Cover Page --- #page( numbering: none, margin: (x: 15mm, y: 20mm), fill: series-colors.cover-bg, )[ #set text(fill: series-colors.cover-fg) #v(1fr) #align(center)[ #block(width: 100%)[ #set text(font: series-fonts.heading) // Title #text(size: 18pt, weight: "bold")[ #data.title ] #if data.at("subtitle", default: none) != none { v(0.3em) text(size: 11pt, fill: series-colors.cover-fg.lighten(20%))[ #data.subtitle ] } #v(1em) #line(length: 40%, stroke: 0.5pt + series-colors.cover-fg.darken(40%)) #v(1em) // Author #if data.at("author", default: none) != none { text(size: 10pt)[ #data.author ] } ] ] #v(1fr) #align(center)[ #text(size: 7pt, fill: series-colors.cover-fg.darken(40%))[ rpubs ] ] ] // --- Table of Contents (if there are headings) --- #let has-headings = data.sections.any(s => s.at("heading", default: none) != none) #if has-headings { page(numbering: none)[ #v(2em) #text(font: series-fonts.heading, size: 12pt, weight: "bold", fill: series-colors.accent)[Contents] #v(1em) #series-rule() #v(0.5em) #for (i, section) in data.sections.enumerate() { if section.at("heading", default: none) != none { let level = section.at("level", default: 1) let indent = (level - 1) * 1em pad(left: indent)[ #text(size: 9pt)[#section.heading] ] v(0.2em) } } ] } // --- Body Content --- #for section in data.sections { // Section heading if section.at("heading", default: none) != none { let level = section.at("level", default: 1) if level == 1 { heading(level: 1)[#section.heading] } else if level == 2 { heading(level: 2)[#section.heading] } else { heading(level: 3)[#section.heading] } } // Content blocks for item in section.at("blocks", default: ()) { if item.type == "paragraph" { par[#item.text] } else if item.type == "quote" { pad(left: 1em)[ #block( inset: (left: 8pt, y: 4pt), stroke: (left: 2pt + series-colors.accent), )[ #set text(style: "italic", size: 8.5pt) #item.text #if item.at("attribution", default: none) != none { v(0.2em) align(right)[ #text(size: 7.5pt, fill: series-colors.muted)[— #item.attribution] ] } ] ] } else if item.type == "list" { if item.at("ordered", default: false) { enum(..item.items.map(entry => [#entry])) } else { list(..item.items.map(entry => [#entry])) } } else if item.type == "code" { raw(block: true, lang: item.at("language", default: none), item.code) } else if item.type == "separator" { series-separator() } } } // --- Colophon (back page) --- #pagebreak() #v(1fr) #series-rule() #v(0.5em) #set text(size: 7pt, fill: series-colors.muted) #if data.at("title", default: none) != none [ *#data.title* #if data.at("author", default: none) != none [ by #data.author] #v(0.3em) ] #[ Typeset with rPubs. \ Formatted for standardized pocket-book printing. ] #v(0.5em) #align(center)[ #text(size: 6pt)[rpubs · drop in a document · get a book] ]