@airmark/quiver 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.
Files changed (77) hide show
  1. package/Quiver.yaml +2 -0
  2. package/README.md +92 -0
  3. package/index.d.ts +16 -0
  4. package/index.js +28 -0
  5. package/package.json +44 -0
  6. package/quills/af4141/0.1.0/Quill.yaml +95 -0
  7. package/quills/af4141/0.1.0/assets/Figtree-Bold.ttf +0 -0
  8. package/quills/af4141/0.1.0/assets/Figtree-Italic.ttf +0 -0
  9. package/quills/af4141/0.1.0/assets/Figtree-Regular.ttf +0 -0
  10. package/quills/af4141/0.1.0/assets/GNU General Public License.txt +340 -0
  11. package/quills/af4141/0.1.0/assets/NimbusRomNo9L-Med.otf +0 -0
  12. package/quills/af4141/0.1.0/assets/NimbusRomNo9L-MedIta.otf +0 -0
  13. package/quills/af4141/0.1.0/assets/NimbusRomNo9L-Reg.otf +0 -0
  14. package/quills/af4141/0.1.0/assets/NimbusRomNo9L-RegIta.otf +0 -0
  15. package/quills/af4141/0.1.0/design/TASK.md +20 -0
  16. package/quills/af4141/0.1.0/design/af4141.pdf +0 -0
  17. package/quills/af4141/0.1.0/example.md +86 -0
  18. package/quills/af4141/0.1.0/packages/typst-af4141/FIELDS.json +3170 -0
  19. package/quills/af4141/0.1.0/packages/typst-af4141/form.typ +538 -0
  20. package/quills/af4141/0.1.0/packages/typst-af4141/lib.typ +270 -0
  21. package/quills/af4141/0.1.0/packages/typst-af4141/page1.png +0 -0
  22. package/quills/af4141/0.1.0/packages/typst-af4141/page2.png +0 -0
  23. package/quills/af4141/0.1.0/packages/typst-af4141/typst.toml +7 -0
  24. package/quills/af4141/0.1.0/plate.typ +67 -0
  25. package/quills/daf1206/0.1.0/DAFForm_1206_prepared.pdf +0 -0
  26. package/quills/daf1206/0.1.0/Quill.yaml +55 -0
  27. package/quills/daf1206/0.1.0/assets/arimo-v35-latin-700.ttf +0 -0
  28. package/quills/daf1206/0.1.0/assets/arimo-v35-latin-700italic.ttf +0 -0
  29. package/quills/daf1206/0.1.0/assets/arimo-v35-latin-italic.ttf +0 -0
  30. package/quills/daf1206/0.1.0/assets/arimo-v35-latin-regular.ttf +0 -0
  31. package/quills/daf1206/0.1.0/example.md +23 -0
  32. package/quills/daf1206/0.1.0/packages/typst-daf1206/FIELDS.json +158 -0
  33. package/quills/daf1206/0.1.0/packages/typst-daf1206/form.typ +36 -0
  34. package/quills/daf1206/0.1.0/packages/typst-daf1206/lib.typ +297 -0
  35. package/quills/daf1206/0.1.0/packages/typst-daf1206/page1.svg +826 -0
  36. package/quills/daf1206/0.1.0/packages/typst-daf1206/page2.svg +497 -0
  37. package/quills/daf1206/0.1.0/packages/typst-daf1206/typst.toml +7 -0
  38. package/quills/daf1206/0.1.0/plate.typ +47 -0
  39. package/quills/daf4392/0.1.0/Quill.yaml +139 -0
  40. package/quills/daf4392/0.1.0/assets/arimo-v35-latin-700.ttf +0 -0
  41. package/quills/daf4392/0.1.0/assets/arimo-v35-latin-700italic.ttf +0 -0
  42. package/quills/daf4392/0.1.0/assets/arimo-v35-latin-italic.ttf +0 -0
  43. package/quills/daf4392/0.1.0/assets/arimo-v35-latin-regular.ttf +0 -0
  44. package/quills/daf4392/0.1.0/assets/page1.png +0 -0
  45. package/quills/daf4392/0.1.0/example.md +34 -0
  46. package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/FIELDS.json +9 -0
  47. package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/form.typ +14 -0
  48. package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/lib.typ +227 -0
  49. package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/typst.toml +7 -0
  50. package/quills/daf4392/0.1.0/plate.typ +86 -0
  51. package/quills/usaf_memo/0.2.0/.quillignore +31 -0
  52. package/quills/usaf_memo/0.2.0/Quill.yaml +255 -0
  53. package/quills/usaf_memo/0.2.0/assets/dod_seal.png +0 -0
  54. package/quills/usaf_memo/0.2.0/assets/dow_seal.png +0 -0
  55. package/quills/usaf_memo/0.2.0/example.md +56 -0
  56. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/.gitignore +7 -0
  57. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/LICENSE +21 -0
  58. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/Cinzel-Regular.ttf +0 -0
  59. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/LICENSE +93 -0
  60. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/CopperplateCC-Heavy.otf +0 -0
  61. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/LICENSE.md +79 -0
  62. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/GNU General Public License.txt +340 -0
  63. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-Med.otf +0 -0
  64. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-MedIta.otf +0 -0
  65. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-Reg.otf +0 -0
  66. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-RegIta.otf +0 -0
  67. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/backmatter.typ +28 -0
  68. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/body.typ +344 -0
  69. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/config.typ +73 -0
  70. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/frontmatter.typ +137 -0
  71. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +111 -0
  72. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/lib.typ +57 -0
  73. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/mainmatter.typ +32 -0
  74. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +321 -0
  75. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/utils.typ +356 -0
  76. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/typst.toml +27 -0
  77. package/quills/usaf_memo/0.2.0/plate.typ +85 -0
@@ -0,0 +1,57 @@
1
+ // lib.typ: Public API for USAF memorandum template
2
+ //
3
+ // This module provides a composable API for creating United States Air Force
4
+ // memorandums that comply with AFH 33-337 "The Tongue and Quill" Chapter 14
5
+ // "The Official Memorandum" formatting standards.
6
+ //
7
+ // AFH 33-337 Chapter 14 specifies exact requirements for:
8
+ // - Margins: 1 inch on all sides (§4)
9
+ // - Font: 12pt Times New Roman (§5)
10
+ // - Date placement: 1.75 inches from top, 1 inch from right (Date section)
11
+ // - Heading elements: MEMORANDUM FOR, FROM, SUBJECT with 2-line spacing
12
+ // - Paragraph numbering: Hierarchical 1., a., (1), (a) format (§2)
13
+ // - Signature block: 4.5 inches from left, never orphaned (Signature Block section)
14
+ // - Backmatter: Attachments, cc:, distribution with specific spacing
15
+ //
16
+ // Key features:
17
+ // - Composable show rules for frontmatter and mainmatter
18
+ // - Function-based backmatter and indorsements for correct ordering
19
+ // - No global state - configuration flows through metadata
20
+ // - Reusable primitives for common rendering tasks
21
+ // - AFH 33-337 compliant formatting throughout
22
+ //
23
+ // Basic usage:
24
+ //
25
+ // #import "@preview/tonguetoquill-usaf-memo:3.0.0": frontmatter, mainmatter, backmatter, indorsement
26
+ //
27
+ // #show: frontmatter.with(
28
+ // subject: "Your Subject Here",
29
+ // memo_for: ("OFFICE/SYMBOL",),
30
+ // memo_from: ("YOUR/SYMBOL",),
31
+ // memo_style: "usaf", // "usaf" (default) or "daf"
32
+ // )
33
+ //
34
+ // #show: mainmatter
35
+ //
36
+ // Your memo body content here.
37
+ // (USAF style auto-numbers per AFH 33-337; DAF style uses unnumbered
38
+ // top-level paragraphs with fixed 0.5in first-line indentation)
39
+ //
40
+ // #backmatter(
41
+ // signature_block: ("NAME, Rank, USAF", "Title"),
42
+ // attachments: (...),
43
+ // cc: (...),
44
+ // )
45
+ //
46
+ // #indorsement(
47
+ // from: "ORG/SYMBOL",
48
+ // to: "RECIPIENT/SYMBOL",
49
+ // signature_block: ("NAME, Rank, USAF", "Title"),
50
+ // )[
51
+ // Indorsement content here.
52
+ // ]
53
+
54
+ #import "frontmatter.typ": frontmatter
55
+ #import "mainmatter.typ": mainmatter
56
+ #import "backmatter.typ": backmatter
57
+ #import "indorsement.typ": indorsement
@@ -0,0 +1,32 @@
1
+ // mainmatter.typ: Mainmatter show rule for USAF memorandum
2
+ //
3
+ // This module implements the mainmatter (body text) of a USAF memorandum per
4
+ // AFH 33-337 Chapter 14 "The Text of the Official Memorandum" (§1-12).
5
+
6
+ #import "body.typ": *
7
+
8
+ /// Mainmatter show rule for USAF memorandum body content.
9
+ ///
10
+ /// AFH 33-337 "The Text of the Official Memorandum" §1-12 requirements:
11
+ /// - Begin text on second line below subject/references
12
+ /// - Single-space text, double-space between paragraphs
13
+ /// - Number and letter each paragraph/subparagraph
14
+ /// - "A single paragraph is not numbered" (§2)
15
+ /// - First paragraph flush left, never indented
16
+ ///
17
+ /// Applies AFH 33-337 paragraph numbering and formatting to the main body
18
+ /// of the memorandum. Automatically detects single vs. multiple paragraphs
19
+ /// to comply with AFH 33-337 numbering requirements.
20
+ ///
21
+ /// When `auto_numbering` is false (set in frontmatter), base-level paragraphs
22
+ /// render flush left without numbering. Only explicitly numbered or bulleted
23
+ /// items enter the numbering hierarchy.
24
+ ///
25
+ /// - content (content): The body content to render
26
+ /// -> content
27
+ #let mainmatter(it) = context {
28
+ let config = query(metadata).last().value
29
+ let auto-numbering = config.at("auto_numbering", default: true)
30
+ let memo-style = config.at("memo_style", default: "usaf")
31
+ render-body(it, auto-numbering: auto-numbering, memo-style: memo-style)
32
+ }
@@ -0,0 +1,321 @@
1
+ // primitives.typ: Reusable rendering primitives for USAF memorandum sections
2
+ //
3
+ // This module implements the visual rendering functions that produce AFH 33-337
4
+ // compliant formatting for all sections of a USAF memorandum. Each function
5
+ // corresponds to specific placement and formatting requirements from Chapter 14.
6
+
7
+ #import "config.typ": *
8
+ #import "utils.typ": *
9
+
10
+ // =============================================================================
11
+ // LETTERHEAD RENDERING
12
+ // =============================================================================
13
+ // AFH 33-337 §1: "Use printed letterhead, computer-generated letterhead, or plain bond paper"
14
+ // Letterhead placement is not explicitly specified in AFH 33-337, but follows
15
+ // standard USAF memo formatting conventions
16
+
17
+ #let render-letterhead(
18
+ title,
19
+ caption,
20
+ font,
21
+ letterhead-seal: none,
22
+ letterhead-seal-subtitle: none,
23
+ ) = {
24
+ font = ensure-array(font)
25
+ title = ensure-string(title)
26
+ caption = ensure-string(caption)
27
+ title = upper(title)
28
+ caption = upper(caption)
29
+
30
+ place(
31
+ dy: 0.625in - spacing.margin,
32
+ box(
33
+ width: 100%,
34
+ fill: none,
35
+ stroke: none,
36
+ [
37
+ #place(
38
+ center + top,
39
+ align(center)[
40
+ #set text(12pt, font: font, fill: LETTERHEAD_COLOR, weight: "bold")
41
+ #title\
42
+ #text(10.5pt)[#caption]
43
+ ],
44
+ )
45
+ ],
46
+ ),
47
+ )
48
+
49
+ if letterhead-seal != none {
50
+ let seal-body = if falsey(letterhead-seal-subtitle) {
51
+ block[
52
+ #fit-box(width: 2in, height: 1in)[#letterhead-seal]
53
+ ]
54
+ } else {
55
+ // Isolate seal column from document `font_size`: stack `em` spacing and subtitle
56
+ // must not scale with body text (see frontmatter `set text(size: font_size)`).
57
+ block(width: 2in)[
58
+ #set text(9pt, font: font, fill: LETTERHEAD_COLOR, weight: "bold")
59
+ #align(left)[
60
+ // Spacing applies between positional stack children only, not one `[…]` body.
61
+ #stack(
62
+ spacing: 0.5em,
63
+ fit-box(width: 2in, height: 1in)[#letterhead-seal],
64
+ upper(ensure-string(letterhead-seal-subtitle)),
65
+ )
66
+ ]
67
+ ]
68
+ }
69
+ place(
70
+ left + top,
71
+ dx: -0.5in,
72
+ dy: -.5in,
73
+ seal-body,
74
+ )
75
+ }
76
+ }
77
+
78
+ // =============================================================================
79
+ // HEADER SECTIONS
80
+ // =============================================================================
81
+ // AFH 33-337 "The Heading Section" specifies exact placement and format for:
82
+ // - Date: 1 inch from right edge, 1.75 inches from top
83
+ // - MEMORANDUM FOR: Second line below date
84
+ // - FROM: Second line below MEMORANDUM FOR
85
+ // - SUBJECT: Second line below FROM
86
+
87
+ // AFH 33-337 "Date": "Place the date 1 inch from the right edge, 1.75 inches from the top"
88
+ #let render-date-section(date, memo-style: "usaf") = {
89
+ align(right)[#display-date(date, memo-style: memo-style)]
90
+ }
91
+
92
+ // AFH 33-337 "MEMORANDUM FOR": "Place 'MEMORANDUM FOR' on the second line below the date"
93
+ #let render-for-section(recipients, cols) = {
94
+ blank-line()
95
+ grid(
96
+ columns: (auto, auto, 1fr),
97
+ "MEMORANDUM FOR",
98
+ " ",
99
+ align(left)[
100
+ #if type(recipients) == array {
101
+ create-auto-grid(recipients, column-gutter: spacing.tab, cols: cols)
102
+ } else {
103
+ recipients
104
+ }
105
+ ],
106
+ )
107
+ }
108
+
109
+ // AFH 33-337 "FROM:": "Place 'FROM:' in uppercase, flush with the left margin,
110
+ // on the second line below the last line of the MEMORANDUM FOR element"
111
+ #let render-from-section(from-info) = {
112
+ blank-line()
113
+ from-info = ensure-string(from-info)
114
+
115
+ grid(
116
+ columns: (auto, auto, 1fr),
117
+ "FROM:", " ", align(left)[#from-info],
118
+ )
119
+ }
120
+
121
+ // AFH 33-337 "SUBJECT:": "In all uppercase letters place 'SUBJECT:', flush with the
122
+ // left margin, on the second line below the last line of the FROM element"
123
+ #let render-subject-section(subject-text) = {
124
+ blank-line()
125
+ grid(
126
+ columns: (auto, auto, 1fr),
127
+ "SUBJECT:", " ", [#subject-text],
128
+ )
129
+ }
130
+
131
+ #let render-references-section(references) = {
132
+ if not falsey(references) {
133
+ blank-line()
134
+ grid(
135
+ columns: (auto, auto, 1fr),
136
+ "References:", " ", enum(..references, numbering: "(a) ", body-indent: 0pt),
137
+ )
138
+ }
139
+ }
140
+
141
+ // =============================================================================
142
+ // SIGNATURE BLOCK
143
+ // =============================================================================
144
+ // AFH 33-337 "Signature Block": "Start the signature block on the fifth line below
145
+ // the last line of text and 4.5 inches from the left edge of the page"
146
+ // AFH 33-337 "Do not place the signature element on a continuation page by itself"
147
+
148
+ #let render-signature-block(signature-lines, signature-blank-lines: 4) = {
149
+ signature-lines = ensure-array(signature-lines)
150
+ // AFH 33-337: "The signature block is never on a page by itself"
151
+ // Note: Perfect enforcement isn't feasible without over-engineering
152
+ // We use weak: false spacing and breakable: false to discourage orphaning
153
+ // AFH 33-337: "fifth line below" = 4 blank lines between text and signature block
154
+ blank-lines(signature-blank-lines, weak: false)
155
+ block(breakable: false)[
156
+ #align(left)[
157
+ // AFH 33-337: "4.5 inches from the left edge of the page"
158
+ // We use (4.5in - margin) because Typst's pad() is relative to the text area, not page edge
159
+ #pad(left: 4.5in - spacing.margin)[
160
+ #text(hyphenate: false)[
161
+ #for line in signature-lines {
162
+ par(hanging-indent: 4 * 0.5em, line)
163
+ }
164
+ ]
165
+ ]
166
+ ]
167
+ ]
168
+ }
169
+
170
+ // =============================================================================
171
+ // ACTION LINE RENDERING
172
+ // =============================================================================
173
+ // Renders the Approve / Disapprove action line for indorsement memos.
174
+ // action: "none" = no action line displayed (hidden), "undecided" = both options
175
+ // rendered plain (no circle), "approve" = Approve circled,
176
+ // "disapprove" = Disapprove circled. The action line is rendered when
177
+ // action is "undecided", "approve", or "disapprove".
178
+
179
+ #let render-action-line(action) = {
180
+ assert(
181
+ action in ("none", "undecided", "approve", "disapprove"),
182
+ message: "action must be \"none\", \"undecided\", \"approve\", or \"disapprove\"",
183
+ )
184
+ blank-line()
185
+ // Circle the selected option using a box with rounded corners
186
+ // Use baseline parameter to maintain vertical text alignment
187
+ let approve-text = if action == "approve" {
188
+ box(stroke: 0.5pt + black, radius: 2pt, inset: 2pt, baseline: 2pt)[Approve]
189
+ } else if action == "disapprove" {
190
+ strike[Approve]
191
+ } else {
192
+ [Approve]
193
+ }
194
+ let disapprove-text = if action == "disapprove" {
195
+ box(stroke: 0.5pt + black, radius: 2pt, inset: 2pt, baseline: 2pt)[Disapprove]
196
+ } else if action == "approve" {
197
+ strike[Disapprove]
198
+ } else {
199
+ [Disapprove]
200
+ }
201
+ // Keep the action line with the following content (body or signature block)
202
+ // using the same sticky-block pattern that body.typ applies to the last
203
+ // paragraph, per AFH 33-337 §11 orphan-prevention rules.
204
+ block(sticky: true)[#approve-text / #disapprove-text]
205
+ }
206
+
207
+ // =============================================================================
208
+ // TABLE RENDERING
209
+ // =============================================================================
210
+ // AFH 33-337 does not specify table formatting, so we follow the general
211
+ // aesthetic principles of the standard: plain black borders, no decorative
212
+ // fills, and the body font inherited throughout.
213
+
214
+ /// Renders a table with USAF memorandum–consistent formatting.
215
+ ///
216
+ /// Applies simple 0.5pt black cell borders and standard padding to any
217
+ /// Typst `table` element, keeping the visual style clean and formal.
218
+ /// Font and size are inherited from the surrounding body text.
219
+ ///
220
+ /// - it (content): The table element to style and render
221
+ /// -> content
222
+ #let render-memo-table(it) = {
223
+ // AFH 33-337 does not specify table formatting, so we follow the general
224
+ // aesthetic principles of the standard: bold headers for clarity.
225
+ show table.cell.where(y: 0): set text(weight: "bold")
226
+ set table(
227
+ stroke: 0.5pt + black,
228
+ inset: (x: 0.5em, y: 0.4em),
229
+ )
230
+ it
231
+ }
232
+
233
+ // =============================================================================
234
+ // BACKMATTER SECTIONS
235
+ // =============================================================================
236
+ // AFH 33-337 "Attachment or Attachments": "Place 'Attachment:' (for a single attachment)
237
+ // or '# Attachments:' (for two or more attachments) at the left margin, on the third
238
+ // line below the signature element"
239
+ // AFH 33-337 "Courtesy Copy Element": "place 'cc:' flush with the left margin, on the
240
+ // second line below the attachment element"
241
+
242
+ #let render-backmatter-section(
243
+ content,
244
+ section-label,
245
+ numbering-style: none,
246
+ continuation-label: none,
247
+ ) = {
248
+ let formatted-content = {
249
+ // Use text() wrapper to prevent section label from being treated as a paragraph
250
+ text()[#section-label]
251
+ linebreak()
252
+ if numbering-style != none {
253
+ let items = ensure-array(content)
254
+ enum(..items, numbering: numbering-style)
255
+ } else {
256
+ ensure-string(content)
257
+ }
258
+ }
259
+
260
+ context {
261
+ let available-space = page.height - here().position().y - 1in
262
+ if measure(formatted-content).height > available-space {
263
+ // Attachments pass continuation-label ("… (listed on next page):" per AFH 33-337).
264
+ // cc: and DISTRIBUTION: use a neutral default — "listed" applies to attachment lists only.
265
+ let continuation-text = if continuation-label != none {
266
+ text()[#continuation-label]
267
+ } else {
268
+ text()[#(section-label + " (continued on next page)")]
269
+ }
270
+ continuation-text
271
+ pagebreak()
272
+ }
273
+ formatted-content
274
+ }
275
+ }
276
+
277
+ #let calculate-backmatter-spacing(is-first-section) = {
278
+ context {
279
+ let line_count = if is-first-section { 2 } else { 1 }
280
+ blank-lines(line_count)
281
+ }
282
+ }
283
+
284
+ #let render-backmatter-sections(
285
+ attachments: none,
286
+ cc: none,
287
+ distribution: none,
288
+ leading-pagebreak: false,
289
+ ) = {
290
+ let has-backmatter = (
291
+ (attachments != none and attachments.len() > 0)
292
+ or (cc != none and cc.len() > 0)
293
+ or (distribution != none and distribution.len() > 0)
294
+ )
295
+
296
+ if leading-pagebreak and has-backmatter {
297
+ pagebreak(weak: true)
298
+ }
299
+
300
+ if attachments != none and attachments.len() > 0 {
301
+ calculate-backmatter-spacing(true)
302
+ let attachment-count = attachments.len()
303
+ let section-label = if attachment-count == 1 { "Attachment:" } else { str(attachment-count) + " Attachments:" }
304
+ let continuation-label = (
305
+ (if attachment-count == 1 { "Attachment" } else { str(attachment-count) + " Attachments" })
306
+ + " (listed on next page):"
307
+ )
308
+ render-backmatter-section(attachments, section-label, numbering-style: "1.", continuation-label: continuation-label)
309
+ }
310
+
311
+ if cc != none and cc.len() > 0 {
312
+ calculate-backmatter-spacing(attachments == none or attachments.len() == 0)
313
+ render-backmatter-section(cc, "cc:")
314
+ }
315
+
316
+ if distribution != none and distribution.len() > 0 {
317
+ calculate-backmatter-spacing((attachments == none or attachments.len() == 0) and (cc == none or cc.len() == 0))
318
+ render-backmatter-section(distribution, "DISTRIBUTION:")
319
+ }
320
+ }
321
+