@airmark/quiver 0.28.0 → 0.29.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 (37) hide show
  1. package/README.md +3 -2
  2. package/package.json +3 -3
  3. package/quills/daf4392/0.1.0/Quill.yaml +2 -2
  4. package/quills/usaf_memo/0.2.0/Quill.yaml +14 -11
  5. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/body.typ +37 -15
  6. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/frontmatter.typ +5 -6
  7. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +5 -3
  8. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +87 -35
  9. package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/utils.typ +34 -1
  10. package/quills/usaf_memo/0.3.0/Quill.yaml +321 -0
  11. package/quills/usaf_memo/0.3.0/assets/dod_seal.png +0 -0
  12. package/quills/usaf_memo/0.3.0/assets/dow_seal.png +0 -0
  13. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/.gitignore +7 -0
  14. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/LICENSE +21 -0
  15. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/Cinzel[wght].ttf +0 -0
  16. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/LICENSE +93 -0
  17. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/CopperplateCC-Bold.otf +0 -0
  18. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/CopperplateCC-Heavy.otf +0 -0
  19. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/LICENSE.md +79 -0
  20. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/LiberationMono/LICENSE +102 -0
  21. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/LiberationMono/LiberationMono-Regular.ttf +0 -0
  22. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/GNU General Public License.txt +340 -0
  23. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-Med.otf +0 -0
  24. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-MedIta.otf +0 -0
  25. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-Reg.otf +0 -0
  26. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/NimbusRomNo9L-RegIta.otf +0 -0
  27. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/backmatter.typ +29 -0
  28. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/body.typ +364 -0
  29. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/config.typ +78 -0
  30. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/frontmatter.typ +242 -0
  31. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +170 -0
  32. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/lib.typ +57 -0
  33. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/mainmatter.typ +27 -0
  34. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +462 -0
  35. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/utils.typ +419 -0
  36. package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/typst.toml +27 -0
  37. package/quills/usaf_memo/0.3.0/plate.typ +120 -0
@@ -0,0 +1,170 @@
1
+ // indorsement.typ: Indorsement rendering for USAF memorandum
2
+ //
3
+ // This module implements indorsements (endorsements) per AFH 33-337 Chapter 14.
4
+ // Indorsements are used to forward memorandums with additional commentary.
5
+ // They follow the format: "1st Ind", "2d Ind", "3d Ind", etc.
6
+ // Each indorsement includes its own body text and signature block.
7
+ //
8
+ // Note: When using #show: indorsement.with(...), the indorsement wraps the
9
+ // entire remainder of the document. This works for a single indorsement at
10
+ // the end of a file. For multiple indorsements, use the function call syntax:
11
+ // #indorsement(...)[Body text...]
12
+
13
+ #import "primitives.typ": *
14
+ #import "body.typ": *
15
+
16
+ #let indorsement(
17
+ from: none,
18
+ to: none,
19
+ signature_block: none,
20
+ signature_blank_lines: 4,
21
+ signing_field: none,
22
+ date: none,
23
+ // Format of indorsement: "standard" (same page), "informal" (no header), or "separate_page" (starts on new page)
24
+ format: "standard",
25
+ // Decision action. `none` (default) displays no action line at all.
26
+ // Approval authority pair: "approve" or "disapprove" circles the selected
27
+ // option; "undecided" displays the pair with neither circled.
28
+ // Coordination pair: "concur" or "nonconcur" circles the selected option;
29
+ // "undecided_concur" displays the pair with neither circled.
30
+ action: none,
31
+ content,
32
+ ) = {
33
+ // Validate format parameter
34
+ assert(
35
+ format in ("standard", "informal", "separate_page"),
36
+ message: "format must be \"standard\", \"informal\", or \"separate_page\"",
37
+ )
38
+
39
+ if format != "informal" {
40
+ assert(from != none, message: "from is required")
41
+ assert(to != none, message: "to is required")
42
+ }
43
+
44
+
45
+ let actual_date = date
46
+ let ind_from = first-or-value(from)
47
+ let ind_for = to
48
+
49
+ // An empty body (e.g. a KIND with only an action selected and no markdown
50
+ // body) collapses to zero rendered layout via render-body's filter. To
51
+ // make the "empty body takes no layout space" guarantee end-to-end, also
52
+ // suppress the spacing the surrounding code reserves *for* the body:
53
+ // the header→body gap (when no action is present) and the action→body
54
+ // trailing gap. Without this, an empty body still leaves an extra
55
+ // blank-line stride above the signature, pushing it off the AFH 33-337
56
+ // "fifth line below the last line of text" anchor.
57
+ // The plate calls indorsement with `[]` when the markdown body is empty
58
+ // or whitespace-only; comparing against `[]` reliably detects that.
59
+ let body_empty = content == []
60
+
61
+ let effective_action = if action == none or type(action) != str or action.trim() == "" {
62
+ none
63
+ } else {
64
+ action
65
+ }
66
+
67
+ if format != "informal" {
68
+ // Step the counter BEFORE the context block to avoid read-then-update loop
69
+ counters.indorsement.step()
70
+
71
+ context {
72
+ let config = query(<usaf-memo-config>).first().value
73
+ let memo-style = config.at("memo_style", default: "usaf")
74
+ let original_subject = config.subject
75
+ let original_date = config.original_date
76
+ let original_from = config.original_from
77
+
78
+ // Read the counter value (already stepped above)
79
+ let indorsement_number = counters.indorsement.get().at(0, default: 1)
80
+ let indorsement_label = format-indorsement-number(indorsement_number)
81
+
82
+ let ind_date = align(right)[#if actual_date != none { display-date(actual_date, memo-style: memo-style) } else { date-placeholder-line() }]
83
+
84
+ // Separate-page header body: restates the original memo's identity (FROM,
85
+ // date, subject) on its own line, since the indorsement no longer shares a
86
+ // page with the action document. Rendered as a non-breakable, sticky unit
87
+ // so it travels to the next page *with* the content it heads rather than
88
+ // being stranded at the bottom of a page.
89
+ // `original_from` / `original_subject` are content fields, and a content
90
+ // field lowers to a markup block whose newlines read as spaces in the
91
+ // enclosing paragraph — mid-sentence that lands a stray space before the
92
+ // following comma. `box` gives each its own paragraph context, where
93
+ // Typst trims the edge spaces (the same treatment the inline reference
94
+ // gets in `render-subject-section`), and keeps the phrase unbroken.
95
+ let separate-page-body = block(breakable: false, sticky: true)[
96
+ #[#indorsement_label to #box(original_from), #display-date(original_date, memo-style: memo-style), #box(original_subject)]
97
+ #blank-line()
98
+ #grid(columns: (auto, 1fr), ind_from, ind_date)
99
+ #blank-line()
100
+ #grid(columns: (auto, auto, 1fr), "MEMORANDUM FOR", " ", ind_for)
101
+ ]
102
+
103
+ // Standard header: terse "Nth Ind, FROM date" line, used when the
104
+ // indorsement stays on the same page as the action document. Same
105
+ // non-breakable + sticky treatment so the two header lines never split
106
+ // across a page boundary and never detach from the body/signature below.
107
+ let standard-header = block(breakable: false, sticky: true)[
108
+ #blank-line()
109
+ #grid(columns: (auto, 1fr), [#indorsement_label, #box(ind_from)], ind_date)
110
+ #blank-line()
111
+ #grid(columns: (auto, auto, 1fr), "MEMORANDUM FOR", " ", ind_for)
112
+ ]
113
+
114
+ if format == "separate_page" {
115
+ // Explicit separate-page indorsement always begins on a fresh page.
116
+ pagebreak()
117
+ separate-page-body
118
+ } else {
119
+ // AFH 33-337: a standard indorsement that no longer fits on the action
120
+ // document's page moves to a separate page, where it carries the fuller
121
+ // separate-page identifying header (it has lost its visual link to the
122
+ // original). Auto-upgrade to that header when the indorsement is pushed
123
+ // to a new page, rather than printing the terse same-page header at the
124
+ // top of a continuation page where it no longer makes sense.
125
+ //
126
+ // Detection: because the header is a non-breakable, sticky unit, Typst
127
+ // moves it wholesale to the next page when it would not fit — so a
128
+ // pushed indorsement lands at the top content margin. If the header's
129
+ // resolved position is at the top of its page, it was pushed; emit the
130
+ // separate-page body (no extra pagebreak — we are already at page top).
131
+ // Otherwise the header flows in place with the standard form.
132
+ let stride = {
133
+ let s = LINE_STRIDE.get()
134
+ if s == none {
135
+ let one-line = measure(par(spacing: 0pt)[x]).height
136
+ measure(par(spacing: 0pt)[x#linebreak()x]).height - one-line
137
+ } else { s }
138
+ }
139
+ // here().position().y is the resolved flow position of this header. On a
140
+ // continuation page the first content sits at the top margin; allow one
141
+ // line stride of tolerance for baseline/rounding.
142
+ let pushed-to-new-page = here().position().y <= spacing.margin + stride
143
+ if pushed-to-new-page {
144
+ separate-page-body
145
+ } else {
146
+ standard-header
147
+ }
148
+ }
149
+ }
150
+ // Header→content gap. Skipped when there is neither an action line nor
151
+ // body to follow — render-signature-block supplies its own 4-line gap.
152
+ if effective_action != none or not body_empty {
153
+ blank-line()
154
+ }
155
+ }
156
+
157
+ // Show action line only when an action decision is set (not `none`)
158
+ if effective_action != none {
159
+ render-action-line(effective_action, trailing-blank-line: not body_empty)
160
+ }
161
+
162
+ if not body_empty {
163
+ context {
164
+ let memo-style = query(<usaf-memo-config>).first().value.at("memo_style", default: "usaf")
165
+ render-body(content, memo-style: memo-style)
166
+ }
167
+ }
168
+
169
+ render-signature-block(signature_block, signature-blank-lines: signature_blank_lines, signing-field: signing_field)
170
+ }
@@ -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,27 @@
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
+ /// - content (content): The body content to render
22
+ /// -> content
23
+ #let mainmatter(it) = context {
24
+ let config = query(<usaf-memo-config>).first().value
25
+ let memo-style = config.at("memo_style", default: "usaf")
26
+ render-body(it, memo-style: memo-style)
27
+ }