@reactwright/template-book 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Reactwright contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @reactwright/template-book
2
+
3
+ Long-form book template for the Reactwright document engine.
4
+ Trade-paperback dimensions (5.5" × 8.5"), chapter-based flow with
5
+ per-chapter running headers, a serif body face suitable for sustained
6
+ reading, and conventional front-matter / back-matter section roles.
7
+
8
+ ## When to use this over alternatives
9
+
10
+ - Pick `@reactwright/template-book` for novels, memoirs, short
11
+ story collections, or any long-form chaptered prose destined for
12
+ printed-book dimensions.
13
+ - Pick `@reactwright/template-essay` for a single MLA-style essay.
14
+ - Pick `@reactwright/template-report` for technical reports.
15
+
16
+ ## Format conventions
17
+
18
+ - Page: 5.5" × 8.5", trade paperback. `twoSided: true` so running
19
+ chrome mirrors on facing pages.
20
+ - Margins: 0.75" all sides (uniform — see "Limitations" below for
21
+ asymmetric-binding margins).
22
+ - Body: Georgia 10.5pt, line-height 1.35.
23
+ - Title page (`role="title-page"`): title 22pt bold centered,
24
+ author/subtitle 12pt centered.
25
+ - Front-matter sections (`role="front-matter"`): centered heading in
26
+ small caps with extra letter-spacing, centered paragraphs. Use for
27
+ copyright, dedication, epigraph.
28
+ - Chapter sections (`role="chapter"`): page break before each
29
+ chapter, large centered "Chapter N — Title" heading positioned a
30
+ third of the way down the page, justified body paragraphs with
31
+ 1.5em first-line indent (0 indent on the paragraph that follows a
32
+ heading).
33
+ - Section heads inside a chapter: 11pt bold italic, no numbering.
34
+ - Block quotes: 18pt left/right indent, no italic, no first-line
35
+ indent.
36
+ - Back-matter sections (`role="back-matter"`): page break before,
37
+ centered heading without numbering. Use for afterword,
38
+ acknowledgments.
39
+ - Running headers (page 2+): chapter title on the inside (gutter)
40
+ edge, book title on the outside (fore) edge — both italic 9pt.
41
+ - Footer: page number on the outside corner, 9pt.
42
+
43
+ ## Usage
44
+
45
+ ```tsx
46
+ import "reactwright/jsx";
47
+ import { Template } from "@reactwright/template-book";
48
+
49
+ export { Template };
50
+
51
+ export default function MyBook() {
52
+ return (
53
+ <document title="My Novel" author="A. Author">
54
+ <section role="title-page" title="My Novel">
55
+ <p>A. Author</p>
56
+ </section>
57
+
58
+ <section role="front-matter" title="Copyright">
59
+ <p>© 2026 A. Author</p>
60
+ </section>
61
+
62
+ <section role="chapter" title="The First Day">
63
+ <p>It was a bright cold day in April, and the clocks were striking thirteen.</p>
64
+ <p>The body continues here…</p>
65
+ </section>
66
+
67
+ <section role="back-matter" title="Acknowledgments">
68
+ <p>For those who made this possible.</p>
69
+ </section>
70
+ </document>
71
+ );
72
+ }
73
+ ```
74
+
75
+ ## Limitations
76
+
77
+ - **Asymmetric binding margins** (wider inside margin for gutter
78
+ bind, narrower outside margin) are not currently expressed: the
79
+ engine does not yet expose `marginInside` / `marginOutside` on
80
+ `@page`. The template uses uniform 0.75" margins as a compromise.
81
+ Deferred to future engine work.
82
+ - **Roman-numeral front-matter pagination** (lowercase roman for
83
+ front matter, arabic restarting at 1 for body) is not implemented.
84
+ The engine's `<page-number />` always emits `counter(page)` as an
85
+ integer. Deferred to future engine work; the workaround is to
86
+ treat the front matter as unnumbered or accept arabic numbering.
87
+ - **Drop caps** on the first paragraph of each chapter are not
88
+ expressed in the default rules — the styling dialect does not yet
89
+ promote `initial-letter` / `::first-letter` first-letter sizing as
90
+ a typed declaration. Authors can opt in by adding a role-rule with
91
+ `dropCap` (see story-bible mockup) or by writing a small per-book
92
+ rule against pass-through CSS via the standard role mechanism.
93
+
94
+ ## Implementation notes
95
+
96
+ Styling is expressed entirely via the styling dialect (`<styles>` +
97
+ `<rule>`). The exported `BOOK_CSS` is an empty string. Section roles
98
+ (`title-page`, `front-matter`, `chapter`, `back-matter`) are
99
+ plain author-side roles — the template's rules use the `within:
100
+ { kind: "section", role: "<name>" }` selector to scope chapter
101
+ typography. Adding a new section role to the book template is a
102
+ matter of adding a few `<rule>` bindings against the same shape.
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@reactwright/template-book",
3
+ "version": "0.1.0",
4
+ "description": "Long-form chaptered book template (trade paperback) for the Reactwright document engine.",
5
+ "license": "MIT",
6
+ "author": "Reactwright contributors",
7
+ "homepage": "https://github.com/PurpleReverie/reactwright/tree/main/packages/template-book#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/PurpleReverie/reactwright.git",
11
+ "directory": "packages/template-book"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/PurpleReverie/reactwright/issues"
15
+ },
16
+ "keywords": ["reactwright", "template", "book", "novel", "trade-paperback"],
17
+ "type": "module",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./src/index.ts",
21
+ "default": "./src/index.ts"
22
+ }
23
+ },
24
+ "files": [
25
+ "src",
26
+ "LICENSE",
27
+ "README.md"
28
+ ],
29
+ "scripts": {
30
+ "check": "tsc --noEmit"
31
+ },
32
+ "peerDependencies": {
33
+ "reactwright": "workspace:*",
34
+ "react": "^18 || ^19"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.15.18",
38
+ "@types/react": "^19.1.2",
39
+ "react": "^19.1.0",
40
+ "reactwright": "workspace:*",
41
+ "typescript": "^5.8.3"
42
+ }
43
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ // Long-form book helper package. Bundles a Template configured for
2
+ // trade-paperback dimensions (5.5" × 8.5"), chapter-based flow with
3
+ // per-chapter running headers (chapter title on odd pages, book title
4
+ // on even pages), and a serif body face suitable for sustained
5
+ // reading. Front-matter and back-matter sections share the same
6
+ // regime; differentiate via section role rules at the author level.
7
+ export { Template, BOOK_STYLES, BOOK_CSS } from "./template.js";
@@ -0,0 +1,353 @@
1
+ import "reactwright/jsx";
2
+ import { Bibliography } from "../../reactwright/src/userland/Bibliography.js";
3
+
4
+ // Long-form book template. Trade-paperback dimensions (5.5" × 8.5"),
5
+ // chapter-based flow, serif body. Distinguishes three section roles:
6
+ //
7
+ // role="chapter" — body chapter; gets "Chapter N" small-caps
8
+ // eyebrow, large centered title, page break
9
+ // before, first paragraph drop-cap-ready.
10
+ // role="front-matter" — title page, copyright, dedication. Renders
11
+ // centered without chapter numbering. Author
12
+ // supplies the typographic shape via inline
13
+ // content.
14
+ // role="back-matter" — afterword, acknowledgments, etc. Renders as
15
+ // a chapter-like section without numbering.
16
+ //
17
+ // Conventions:
18
+ // • 5.5" × 8.5" page (US trade paperback)
19
+ // • 0.75"/0.75" top/bottom margin, 0.75" inside, 0.625" outside
20
+ // (twoSided: true for mirrored chrome; the binding asymmetry is
21
+ // approximated by uniform margins because the engine does not yet
22
+ // expose marginInside/marginOutside on @page — see the README).
23
+ // • Body: Georgia 10.5pt, line-height 1.35
24
+ // • Chapter title block centered, content begins ~⅓ down the page
25
+ // • Section heads within a chapter: 11pt bold italic, no numbering
26
+ // • Body paragraphs: 1.5em first-line indent, 0 margin (standard
27
+ // book flow). First paragraph after any heading: no indent.
28
+ // • Running header (page 2+): chapter title on odd pages, book
29
+ // title on even pages, page number on outside corner.
30
+ //
31
+ // Slice-1+ dialect only. customCss is empty.
32
+
33
+ export const BOOK_STYLES = `
34
+ .book-frontmatter {
35
+ text-align: center;
36
+ margin: 0 0 18pt 0;
37
+ }
38
+
39
+ .book-frontmatter-heading {
40
+ font-size: 12pt;
41
+ font-weight: normal;
42
+ font-style: normal;
43
+ font-family: 'Georgia', 'Times New Roman', serif;
44
+ text-align: center;
45
+ text-transform: uppercase;
46
+ letter-spacing: 0.2em;
47
+ margin: 0 0 12pt 0;
48
+ text-indent: 0;
49
+ break: after(avoid);
50
+ }
51
+
52
+ .book-frontmatter-p {
53
+ font-size: 10.5pt;
54
+ margin: 0 0 6pt 0;
55
+ text-indent: 0;
56
+ text-align: center;
57
+ }
58
+
59
+ .book-titlepage {
60
+ text-align: center;
61
+ padding: 18pt 0;
62
+ }
63
+
64
+ .book-titlepage-heading {
65
+ font-size: 22pt;
66
+ font-weight: bold;
67
+ font-family: 'Georgia', 'Times New Roman', serif;
68
+ text-align: center;
69
+ margin: 0 0 18pt 0;
70
+ text-indent: 0;
71
+ break: after(avoid);
72
+ }
73
+
74
+ .book-titlepage-p {
75
+ font-size: 12pt;
76
+ margin: 0 0 4pt 0;
77
+ text-indent: 0;
78
+ text-align: center;
79
+ }
80
+
81
+ .book-chapter {
82
+ margin: 0;
83
+ break: before(page);
84
+ }
85
+
86
+ .book-chapter-heading {
87
+ font-size: 16pt;
88
+ font-weight: bold;
89
+ font-family: 'Georgia', 'Times New Roman', serif;
90
+ text-align: center;
91
+ margin: 96pt 0 36pt 0;
92
+ text-indent: 0;
93
+ line-height: 1.2;
94
+ numbering: counter(book-chapter) "Chapter $book-chapter — ";
95
+ break: after(avoid);
96
+ }
97
+
98
+ .book-section-head {
99
+ font-size: 11pt;
100
+ font-weight: bold;
101
+ font-style: italic;
102
+ font-family: 'Georgia', 'Times New Roman', serif;
103
+ text-align: left;
104
+ text-transform: none;
105
+ letter-spacing: 0;
106
+ margin: 12pt 0 2pt 0;
107
+ text-indent: 0;
108
+ break: after(avoid);
109
+ }
110
+
111
+ .book-body-p {
112
+ margin: 0;
113
+ text-indent: 1.5em;
114
+ text-align: justify;
115
+ }
116
+
117
+ .book-heading-adjacent-p {
118
+ text-indent: 0;
119
+ }
120
+
121
+ .book-blockquote {
122
+ margin: 6pt 18pt;
123
+ font-style: normal;
124
+ text-indent: 0;
125
+ }
126
+
127
+ .book-blockquote-p {
128
+ margin: 0;
129
+ text-indent: 0;
130
+ text-align: left;
131
+ }
132
+
133
+ .book-backmatter {
134
+ margin: 0;
135
+ break: before(page);
136
+ }
137
+
138
+ .book-backmatter-heading {
139
+ font-size: 14pt;
140
+ font-weight: bold;
141
+ font-style: normal;
142
+ font-family: 'Georgia', 'Times New Roman', serif;
143
+ text-align: center;
144
+ margin: 36pt 0 18pt 0;
145
+ text-indent: 0;
146
+ break: after(avoid);
147
+ }
148
+
149
+ .book-bibliography {
150
+ font-size: 10pt;
151
+ margin-top: 18pt;
152
+ }
153
+
154
+ .book-bib-heading {
155
+ font-size: 14pt;
156
+ font-weight: bold;
157
+ font-family: 'Georgia', 'Times New Roman', serif;
158
+ text-align: center;
159
+ margin: 36pt 0 18pt 0;
160
+ text-indent: 0;
161
+ break: after(avoid);
162
+ }
163
+
164
+ .book-bib-list {
165
+ list-style: none;
166
+ padding-left: 0;
167
+ margin: 0;
168
+ }
169
+
170
+ .book-bib-entry {
171
+ margin-bottom: 4pt;
172
+ }
173
+
174
+ .book-bib-entry-p {
175
+ margin: 0;
176
+ text-align: left;
177
+ text-indent: -1.4em;
178
+ padding-left: 1.4em;
179
+ }
180
+
181
+ .book-cite {
182
+ color: inherit;
183
+ text-decoration: none;
184
+ }
185
+
186
+ .book-code-inline {
187
+ background: none;
188
+ padding: 0;
189
+ border-radius: 0;
190
+ font-family: 'SFMono-Regular', Consolas, Menlo, monospace;
191
+ font-size: 0.92em;
192
+ }
193
+ `;
194
+
195
+ // BOOK_CSS is empty. All styling is expressed via the dialect's
196
+ // <styles> block + <rule> bindings.
197
+ export const BOOK_CSS = "";
198
+
199
+ export function Template() {
200
+ return (
201
+ <page
202
+ page={{
203
+ size: "5.5in 8.5in",
204
+ marginTop: "0.75in",
205
+ marginBottom: "0.75in",
206
+ marginLeft: "0.75in",
207
+ marginRight: "0.75in",
208
+ twoSided: true
209
+ }}
210
+ typography={{
211
+ fontFamily: "'Georgia', 'Times New Roman', Times, serif",
212
+ fontSize: "10.5pt",
213
+ lineHeight: 1.35,
214
+ textAlign: "justify"
215
+ }}
216
+ >
217
+ <styles>{BOOK_STYLES}</styles>
218
+
219
+ <rule match={{ kind: "title" }} className="book-titlepage-heading" />
220
+ <rule match={{ kind: "author" }} className="book-titlepage-p" />
221
+ <rule match={{ kind: "code" }} className="book-code-inline" />
222
+
223
+ {/* Front-matter sections (copyright, dedication, etc.) */}
224
+ <rule match={{ kind: "section", role: "front-matter" }} className="book-frontmatter" />
225
+ <rule
226
+ match={{ kind: "section-heading", within: { kind: "section", role: "front-matter" } }}
227
+ className="book-frontmatter-heading"
228
+ />
229
+ <rule
230
+ match={{ kind: "paragraph", within: { kind: "section", role: "front-matter" } }}
231
+ className="book-frontmatter-p"
232
+ />
233
+
234
+ {/* Title page (a special front-matter shape — role="title-page") */}
235
+ <rule match={{ kind: "section", role: "title-page" }} className="book-titlepage" />
236
+ <rule
237
+ match={{ kind: "paragraph", within: { kind: "section", role: "title-page" } }}
238
+ className="book-titlepage-p"
239
+ />
240
+
241
+ {/* Chapter sections — large centered title, page break before */}
242
+ <rule match={{ kind: "section", role: "chapter" }} className="book-chapter" />
243
+ <rule
244
+ match={{
245
+ kind: "section-heading",
246
+ depth: 1,
247
+ within: { kind: "section", role: "chapter" }
248
+ }}
249
+ className="book-chapter-heading"
250
+ />
251
+
252
+ {/* Subsection headings inside a chapter — depth 2, plain */}
253
+ <rule
254
+ match={{
255
+ kind: "section-heading",
256
+ depth: 2,
257
+ within: { kind: "section", role: "chapter" }
258
+ }}
259
+ className="book-section-head"
260
+ />
261
+
262
+ {/* Body paragraphs inside chapters — exclude blockquotes */}
263
+ <rule
264
+ match={{
265
+ kind: "paragraph",
266
+ within: { kind: "section", role: "chapter" },
267
+ not: { within: { kind: "blockquote" } }
268
+ }}
269
+ className="book-body-p"
270
+ />
271
+ <rule
272
+ match={{
273
+ kind: "paragraph",
274
+ within: { kind: "section", role: "chapter" },
275
+ follows: { kind: "section-heading" }
276
+ }}
277
+ className="book-heading-adjacent-p"
278
+ />
279
+
280
+ {/* Block quotes — modest indent, no italic */}
281
+ <rule match={{ kind: "blockquote" }} className="book-blockquote" />
282
+ <rule
283
+ match={{ kind: "paragraph", within: { kind: "blockquote" } }}
284
+ className="book-blockquote-p"
285
+ />
286
+
287
+ {/* Back-matter sections (afterword, acknowledgments). */}
288
+ <rule match={{ kind: "section", role: "back-matter" }} className="book-backmatter" />
289
+ <rule
290
+ match={{ kind: "section-heading", within: { kind: "section", role: "back-matter" } }}
291
+ className="book-backmatter-heading"
292
+ />
293
+ <rule
294
+ match={{
295
+ kind: "paragraph",
296
+ within: { kind: "section", role: "back-matter" }
297
+ }}
298
+ className="book-body-p"
299
+ />
300
+
301
+ {/* Cites pass through as plain superscript-style references */}
302
+ <rule match={{ kind: "cite" }} className="book-cite" />
303
+
304
+ {/* Bibliography (userland) — only present if author calls it. */}
305
+ <rule match={{ kind: "section", role: "bibliography" }} className="book-bibliography" />
306
+ <rule
307
+ match={{ kind: "section-heading", within: { kind: "section", role: "bibliography" } }}
308
+ className="book-bib-heading"
309
+ />
310
+ <rule
311
+ match={{ kind: "list", within: { kind: "section", role: "bibliography" } }}
312
+ className="book-bib-list"
313
+ />
314
+ <rule
315
+ match={{ kind: "item", within: { kind: "section", role: "bibliography" } }}
316
+ className="book-bib-entry"
317
+ />
318
+ <rule
319
+ match={{ kind: "paragraph", within: { kind: "section", role: "bibliography" } }}
320
+ className="book-bib-entry-p"
321
+ />
322
+
323
+ {/* Running headers — chapter title on the inside, book title on
324
+ the outside, page numbers on the outside corner. Two-sided
325
+ mirroring is automatic for inside/outside anchors. */}
326
+ <header
327
+ anchor="top-inside"
328
+ when="not-first-page"
329
+ typography={{ fontSize: "9pt", fontStyle: "italic" }}
330
+ >
331
+ <running name="chapter-title" />
332
+ </header>
333
+ <header
334
+ anchor="top-outside"
335
+ when="not-first-page"
336
+ typography={{ fontSize: "9pt", fontStyle: "italic" }}
337
+ >
338
+ <running name="document-title" />
339
+ </header>
340
+ <footer anchor="bottom-outside" typography={{ fontSize: "9pt" }}>
341
+ <page-number />
342
+ </footer>
343
+
344
+ <stack gap="0">
345
+ <region>
346
+ <slot name="title" />
347
+ <slot name="author" />
348
+ <slot name="body" />
349
+ </region>
350
+ </stack>
351
+ </page>
352
+ );
353
+ }