@airmark/quiver 0.10.0 → 0.11.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/package.json +1 -1
- package/quills/usaf_memo/0.2.0/Quill.yaml +4 -3
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/CopperplateCC-Bold.otf +0 -0
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/config.typ +1 -1
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +26 -8
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +10 -6
- package/quills/usaf_memo/0.2.0/plate.typ +18 -4
package/package.json
CHANGED
|
@@ -244,12 +244,13 @@ card_types:
|
|
|
244
244
|
title: Action Decision
|
|
245
245
|
type: string
|
|
246
246
|
enum:
|
|
247
|
+
- none
|
|
247
248
|
- undecided
|
|
248
249
|
- approve
|
|
249
250
|
- disapprove
|
|
250
251
|
ui:
|
|
251
252
|
group: Addressing
|
|
252
|
-
description: "Action taken by the endorser. Use '
|
|
253
|
+
description: "Action taken by the endorser. Use 'none' to hide the Approve/Disapprove line entirely, 'undecided' to display the line with neither option circled, 'approve' or 'disapprove' to circle the selected option."
|
|
253
254
|
attachments:
|
|
254
255
|
title: Attachments for this endorsement
|
|
255
256
|
type: array
|
|
@@ -263,8 +264,8 @@ card_types:
|
|
|
263
264
|
group: Additional
|
|
264
265
|
description: List of office symbols to receive copies of this endorsement.
|
|
265
266
|
date:
|
|
266
|
-
title: Date of endorsement (YYYY-MM-DD)
|
|
267
|
+
title: Date of endorsement (YYYY-MM-DD); defaults to today
|
|
267
268
|
type: date
|
|
268
269
|
ui:
|
|
269
270
|
group: Additional
|
|
270
|
-
description: Date
|
|
271
|
+
description: "YYYY-MM-DD. Date the endorser signs/forwards the memo (per AFH 33-337 Ch. 14, this is distinct from the originating memo's date). Leave blank to use today's date."
|
|
Binary file
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// =============================================================================
|
|
20
20
|
// AFH 33-337 §5: "Use 12 point Times New Roman font for text"
|
|
21
21
|
|
|
22
|
-
#let DEFAULT_LETTERHEAD_FONTS = ("NimbusRomNo9L", "times new roman")
|
|
22
|
+
#let DEFAULT_LETTERHEAD_FONTS = ("Copperplate CC", "NimbusRomNo9L", "times new roman")
|
|
23
23
|
#let DEFAULT_BODY_FONTS = ("NimbusRomNo9L", "times new roman") // AFH 33-337 §5: Times New Roman required
|
|
24
24
|
#let LETTERHEAD_COLOR = rgb("#204093") // Faded USAF blue for letterhead
|
|
25
25
|
|
|
@@ -45,6 +45,18 @@
|
|
|
45
45
|
let ind_from = first-or-value(from)
|
|
46
46
|
let ind_for = to
|
|
47
47
|
|
|
48
|
+
// An empty body (e.g. a CARD with only an action selected and no markdown
|
|
49
|
+
// body) collapses to zero rendered layout via render-body's filter. To
|
|
50
|
+
// make the "empty body takes no layout space" guarantee end-to-end, also
|
|
51
|
+
// suppress the spacing the surrounding code reserves *for* the body:
|
|
52
|
+
// the header→body gap (when no action is present) and the action→body
|
|
53
|
+
// trailing gap. Without this, an empty body still leaves an extra
|
|
54
|
+
// blank-line stride above the signature, pushing it off the AFH 33-337
|
|
55
|
+
// "fifth line below the last line of text" anchor.
|
|
56
|
+
// The plate calls indorsement with `[]` when the markdown body is empty
|
|
57
|
+
// or whitespace-only; comparing against `[]` reliably detects that.
|
|
58
|
+
let body_empty = content == []
|
|
59
|
+
|
|
48
60
|
if format != "informal" {
|
|
49
61
|
// Step the counter BEFORE the context block to avoid read-then-update loop
|
|
50
62
|
counters.indorsement.step()
|
|
@@ -89,20 +101,26 @@
|
|
|
89
101
|
)
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
|
-
|
|
104
|
+
// Header→content gap. Skipped when there is neither an action line nor
|
|
105
|
+
// body to follow — render-signature-block supplies its own 4-line gap.
|
|
106
|
+
if (action != none and action != "none") or not body_empty {
|
|
107
|
+
blank-line()
|
|
108
|
+
}
|
|
93
109
|
}
|
|
94
110
|
|
|
95
111
|
// Show action line only when an action decision is set (not `none`)
|
|
96
|
-
if action != none {
|
|
97
|
-
render-action-line(action)
|
|
112
|
+
if action != none and action != "none" {
|
|
113
|
+
render-action-line(action, trailing-blank-line: not body_empty)
|
|
98
114
|
}
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
let
|
|
103
|
-
|
|
116
|
+
if not body_empty {
|
|
117
|
+
context {
|
|
118
|
+
let memo-style = {
|
|
119
|
+
let items = query(metadata)
|
|
120
|
+
if items.len() > 0 { items.last().value.at("memo_style", default: "usaf") } else { "usaf" }
|
|
121
|
+
}
|
|
122
|
+
render-body(content, memo-style: memo-style)
|
|
104
123
|
}
|
|
105
|
-
render-body(content, memo-style: memo-style)
|
|
106
124
|
}
|
|
107
125
|
|
|
108
126
|
render-signature-block(signature_block, signature-blank-lines: signature_blank_lines)
|
|
@@ -199,9 +199,10 @@
|
|
|
199
199
|
// action: "none" = no action line displayed (hidden), "undecided" = both options
|
|
200
200
|
// rendered plain (no circle), "approve" = Approve circled,
|
|
201
201
|
// "disapprove" = Disapprove circled. The action line is rendered when
|
|
202
|
-
// action is "undecided", "approve", or "disapprove".
|
|
202
|
+
// action is "undecided", "approve", or "disapprove". "none" suppresses
|
|
203
|
+
// the line entirely (handled by the caller).
|
|
203
204
|
|
|
204
|
-
#let render-action-line(action) = {
|
|
205
|
+
#let render-action-line(action, trailing-blank-line: true) = {
|
|
205
206
|
assert(
|
|
206
207
|
action in ("none", "undecided", "approve", "disapprove"),
|
|
207
208
|
message: "action must be \"none\", \"undecided\", \"approve\", or \"disapprove\"",
|
|
@@ -230,10 +231,13 @@
|
|
|
230
231
|
// using the same sticky-block pattern that body.typ applies to the last
|
|
231
232
|
// paragraph, per AFH 33-337 §11 orphan-prevention rules.
|
|
232
233
|
block(sticky: true)[#approve-text / #disapprove-text]
|
|
233
|
-
// Trailing blank-line
|
|
234
|
-
//
|
|
235
|
-
// the gap
|
|
236
|
-
|
|
234
|
+
// Trailing blank-line places the body's first paragraph one line below
|
|
235
|
+
// the action, mirroring the gap above it. Suppressed when the body is
|
|
236
|
+
// empty so the signature block's own 4-line gap lands on AFH 33-337's
|
|
237
|
+
// "fifth line below the last line of text" anchor.
|
|
238
|
+
if trailing-blank-line {
|
|
239
|
+
blank-line()
|
|
240
|
+
}
|
|
237
241
|
}
|
|
238
242
|
|
|
239
243
|
// =============================================================================
|
|
@@ -71,6 +71,21 @@
|
|
|
71
71
|
// Indorsements - iterate through CARDS array and filter by CARD type
|
|
72
72
|
#for card in data.CARDS {
|
|
73
73
|
if card.CARD == "indorsement" {
|
|
74
|
+
// The quillmark helper leaves an unset/whitespace-only markdown body as
|
|
75
|
+
// the empty string `""`; only non-empty bodies are eval'd into content.
|
|
76
|
+
// Pass truly empty content (`[]`) in the empty case so indorsement can
|
|
77
|
+
// collapse the body's surrounding spacing.
|
|
78
|
+
let body = card.at("BODY", default: "")
|
|
79
|
+
let body_content = if type(body) == str { [] } else { body }
|
|
80
|
+
// Per AFH 33-337 Ch. 14, an indorsement is dated when the endorser signs
|
|
81
|
+
// it (distinct from the originating memo's date). Default to today when
|
|
82
|
+
// the card omits or leaves the date blank.
|
|
83
|
+
let card_date = card.at("date", default: none)
|
|
84
|
+
let resolved_date = if card_date == none or card_date == "" {
|
|
85
|
+
datetime.today()
|
|
86
|
+
} else {
|
|
87
|
+
card_date
|
|
88
|
+
}
|
|
74
89
|
indorsement(
|
|
75
90
|
from: card.at("from", default: ""),
|
|
76
91
|
to: card.at("for", default: ""),
|
|
@@ -78,10 +93,9 @@
|
|
|
78
93
|
..if "attachments" in card { (attachments: card.attachments) },
|
|
79
94
|
..if "cc" in card { (cc: card.cc) },
|
|
80
95
|
format: card.at("format", default: "standard"),
|
|
81
|
-
|
|
96
|
+
date: resolved_date,
|
|
82
97
|
..if "action" in card { (action: card.action) },
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
]
|
|
98
|
+
body_content,
|
|
99
|
+
)
|
|
86
100
|
}
|
|
87
101
|
}
|