@airmark/quiver 0.30.0 → 0.32.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/README.md +1 -0
- package/package.json +4 -4
- package/quills/af4141/0.1.0/plate.typ +11 -19
- package/quills/afmc_moa/0.0.1/Quill.yaml +289 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/fonts/NimbusRomanNo9L/GNU General Public License.txt +340 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/fonts/NimbusRomanNo9L/NimbusRomNo9L-Med.otf +0 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/fonts/NimbusRomanNo9L/NimbusRomNo9L-MedIta.otf +0 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/fonts/NimbusRomanNo9L/NimbusRomNo9L-Reg.otf +0 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/fonts/NimbusRomanNo9L/NimbusRomNo9L-RegIta.otf +0 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/attachment.typ +51 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/backmatter.typ +66 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/body.typ +126 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/config.typ +31 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/frontmatter.typ +74 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/lib.typ +41 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/mainmatter.typ +5 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/src/utils.typ +126 -0
- package/quills/afmc_moa/0.0.1/packages/typst-afmc-moa/typst.toml +19 -0
- package/quills/afmc_moa/0.0.1/plate.typ +116 -0
- package/quills/daf1206/0.1.0/plate.typ +10 -10
- package/quills/daf4392/0.1.0/plate.typ +13 -13
- package/quills/usaf_memo/0.2.0/Quill.yaml +0 -2
- package/quills/usaf_memo/0.2.0/plate.typ +33 -28
- package/quills/usaf_memo/0.3.0/Quill.yaml +25 -44
- package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/body.typ +30 -25
- package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +18 -6
- package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/lib.typ +1 -0
- package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +56 -31
- package/quills/usaf_memo/0.3.0/packages/tonguetoquill-usaf-memo/src/utils.typ +41 -33
- package/quills/usaf_memo/0.3.0/plate.typ +108 -44
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
#import "@local/quillmark-helper:0.1.0": data, signature-field
|
|
2
|
-
#import "@local/tonguetoquill-usaf-memo:4.0.0":
|
|
1
|
+
#import "@local/quillmark-helper:0.1.0": data, display, form-field, signature-field
|
|
2
|
+
#import "@local/tonguetoquill-usaf-memo:4.0.0": (
|
|
3
|
+
backmatter, date-pattern, frontmatter, indorsement, mainmatter,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
// A memo has no "no style" state, so the blank takes the package's default.
|
|
7
|
+
// Resolved once here: `frontmatter` and the date's pattern must agree.
|
|
8
|
+
#let memo_style = if data.memo_style != "" { data.memo_style } else { "usaf" }
|
|
3
9
|
|
|
4
10
|
// The letterhead arrives as one ordered array of lines. Element 0 is the title,
|
|
5
11
|
// set larger; the rest are caption lines beneath it. A single element renders
|
|
@@ -8,54 +14,77 @@
|
|
|
8
14
|
// leaves no glyphs and takes no space from the flow, and the seal stands alone.
|
|
9
15
|
#let letterhead_lines = data.letterhead_title
|
|
10
16
|
|
|
17
|
+
// Body text size, in points. Also the height of one line of the indorsement
|
|
18
|
+
// header, which is what an omitted indorsement date reserves for its fill-in
|
|
19
|
+
// widget (`date-placeholder-slot`, whose slot is `1em` tall and 1in wide).
|
|
20
|
+
#let body_font_size = data.font_size * 1pt
|
|
21
|
+
|
|
11
22
|
// Frontmatter configuration
|
|
12
23
|
#show: frontmatter.with(
|
|
13
24
|
// Letterhead configuration
|
|
14
25
|
letterhead_title: letterhead_lines.at(0, default: ""),
|
|
15
26
|
letterhead_caption: if letterhead_lines.len() > 1 { letterhead_lines.slice(1) } else { () },
|
|
16
|
-
letterhead_seal_subtitle: data.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
letterhead_seal_subtitle: data.letterhead_seal_subtitle,
|
|
28
|
+
// Enum blank is `""`, not a seal. Omit so the package renders none rather
|
|
29
|
+
// than treating the blank as DoW.
|
|
30
|
+
..if data.letterhead_seal != "" {
|
|
31
|
+
(letterhead_seal: image(
|
|
32
|
+
if data.letterhead_seal == "dod" {
|
|
33
|
+
"assets/dod_seal.png"
|
|
34
|
+
} else {
|
|
35
|
+
"assets/dow_seal.png"
|
|
36
|
+
}
|
|
37
|
+
))
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
// Date. `data.date` is the native `datetime` and would render identically,
|
|
41
|
+
// but its ink would be born inside the package and carry no schema address.
|
|
42
|
+
// `display` places the field's *content* projection instead: the glyphs are
|
|
43
|
+
// born in the generated helper, so the memo date stays click-to-edit however
|
|
44
|
+
// deep the package formats it. A blank date yields `none`, which is what
|
|
45
|
+
// `frontmatter`'s `datetime.today()` fallback keys on.
|
|
46
|
+
date: display("date", date-pattern(memo-style: memo_style)),
|
|
27
47
|
|
|
28
48
|
// Receiver information
|
|
29
49
|
memo_for: data.memo_for,
|
|
30
50
|
|
|
31
51
|
// Sender information (omitted for Memorandum for Record)
|
|
32
|
-
..if data.
|
|
52
|
+
..if data.memo_from.len() > 0 { (memo_from: data.memo_from) },
|
|
33
53
|
|
|
34
54
|
// Subject line
|
|
35
55
|
subject: data.subject,
|
|
36
56
|
|
|
37
57
|
// Optional references
|
|
38
|
-
..if
|
|
58
|
+
..if data.references.len() > 0 { (references: data.references) },
|
|
39
59
|
|
|
40
60
|
// Optional footer tag line
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
footer_tag_line: data.tag_line,
|
|
62
|
+
|
|
63
|
+
// The blank reads as no banner, which is what the package's own
|
|
64
|
+
// `classification_level: none` default means.
|
|
65
|
+
classification_level: data.classification.value,
|
|
66
|
+
|
|
67
|
+
dissemination: data.dissemination,
|
|
68
|
+
|
|
69
|
+
// CUI designation indicator block fields (DoDM 5200.48). `classification`
|
|
70
|
+
// declares a `CUI` variant, so these four exist only where the discriminant
|
|
71
|
+
// reads CUI, and the branch is what makes reading them total: inside it every
|
|
72
|
+
// declared field of that world is present, outside it none is. The package's
|
|
73
|
+
// own `cui_*: none` defaults cover the worlds that omit them.
|
|
74
|
+
..if data.classification.value == "CUI" {
|
|
75
|
+
(
|
|
76
|
+
cui_controlled_by: data.classification.controlled_by,
|
|
77
|
+
cui_category: data.classification.category,
|
|
78
|
+
cui_limited_dissemination: data.classification.limited_dissemination,
|
|
79
|
+
cui_poc: data.classification.poc,
|
|
80
|
+
)
|
|
81
|
+
},
|
|
53
82
|
|
|
54
|
-
// USAF vs DAF memorandum style (date format, body indentation)
|
|
55
|
-
memo_style:
|
|
83
|
+
// USAF vs DAF memorandum style (date format, body indentation).
|
|
84
|
+
memo_style: memo_style,
|
|
56
85
|
|
|
57
86
|
// Font size
|
|
58
|
-
font_size:
|
|
87
|
+
font_size: body_font_size,
|
|
59
88
|
|
|
60
89
|
// List recipients in vertical list
|
|
61
90
|
memo_for_cols: 1,
|
|
@@ -76,18 +105,38 @@
|
|
|
76
105
|
signing_field: signature-field("Signature", field: "signature_block"),
|
|
77
106
|
|
|
78
107
|
// Optional cc
|
|
79
|
-
..if
|
|
108
|
+
..if data.cc.len() > 0 { (cc: data.cc) },
|
|
80
109
|
|
|
81
110
|
// Optional distribution
|
|
82
|
-
..if
|
|
111
|
+
..if data.distribution.len() > 0 { (distribution: data.distribution) },
|
|
83
112
|
|
|
84
113
|
// Optional attachments
|
|
85
|
-
..if
|
|
114
|
+
..if data.attachments.len() > 0 { (attachments: data.attachments) },
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
// The action line's wording follows the indorsement's place in the chain, not
|
|
118
|
+
// an endorser's choice: the last indorsement is the approval authority and
|
|
119
|
+
// reads Approve / Disapprove, every one before it is a coordinating official
|
|
120
|
+
// and reads Concur / Nonconcur. Only this loop can see whether an indorsement
|
|
121
|
+
// is the last one, so the position is resolved here and passed down. Cards of
|
|
122
|
+
// other kinds may interleave, so the last indorsement is the last card *of
|
|
123
|
+
// this kind*, not the last card. `-1` never matches a real index, which is the
|
|
124
|
+
// wanted result when there are no indorsements at all.
|
|
125
|
+
// Parenthesized so the method chain can span lines: in markup, a `#let` whose
|
|
126
|
+
// expression ends at a line break stops there, and the next line's leading
|
|
127
|
+
// `.at(…)` would be read as text.
|
|
128
|
+
#let last_indorsement_index = (
|
|
129
|
+
data
|
|
130
|
+
.at("$cards")
|
|
131
|
+
.enumerate()
|
|
132
|
+
.filter(entry => entry.at(1).at("$kind", default: none) == "indorsement")
|
|
133
|
+
.map(entry => entry.at(0))
|
|
134
|
+
.at(-1, default: -1)
|
|
86
135
|
)
|
|
87
136
|
|
|
88
137
|
// Indorsements - iterate through CARDS array and filter by CARD tag
|
|
89
138
|
#for (i, card) in data.at("$cards").enumerate() {
|
|
90
|
-
if card.at("$kind") == "indorsement" {
|
|
139
|
+
if card.at("$kind", default: none) == "indorsement" {
|
|
91
140
|
// The quillmark helper leaves an unset/whitespace-only markdown body as
|
|
92
141
|
// the empty string `""`; only non-empty bodies are eval'd into content.
|
|
93
142
|
// Pass truly empty content (`[]`) in the empty case so indorsement can
|
|
@@ -96,14 +145,15 @@
|
|
|
96
145
|
let body_content = if type(body) == str { [] } else { body }
|
|
97
146
|
// Per AFH 33-337 Ch. 14, an indorsement is dated when the endorser signs
|
|
98
147
|
// it (distinct from the originating memo's date). The signing date is
|
|
99
|
-
// generally unknown at compile time
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
148
|
+
// generally unknown at compile time, so a blank or omitted date leaves the
|
|
149
|
+
// date slot fillable rather than stamping the compile date into it.
|
|
150
|
+
// `display` takes an address, so a per-card call yields a per-card region
|
|
151
|
+
// even though every iteration shares one `card` loop variable, and it
|
|
152
|
+
// returns `none` for a blank date — the fill-in case below.
|
|
153
|
+
let resolved_date = display(
|
|
154
|
+
card.at("$path") + "date",
|
|
155
|
+
date-pattern(memo-style: memo_style),
|
|
156
|
+
)
|
|
107
157
|
// The card's `$path` prefix composes its canonical schema addresses
|
|
108
158
|
// (`$cards.indorsement.<n>.…`, per-kind ordinal) — the absolute loop
|
|
109
159
|
// index `i` is NOT that ordinal once kinds interleave, so it stays a
|
|
@@ -118,9 +168,23 @@
|
|
|
118
168
|
"Ind_" + str(i) + "_Signature",
|
|
119
169
|
field: card.at("$path") + "signature_block",
|
|
120
170
|
),
|
|
121
|
-
|
|
171
|
+
..if card.format != "" { (format: card.format) },
|
|
122
172
|
date: resolved_date,
|
|
123
|
-
|
|
173
|
+
// An omitted date becomes an empty AcroForm text box the endorser types
|
|
174
|
+
// the signing date into, sized to the slot the package reserves for it.
|
|
175
|
+
// Built only when there is no date to print: a widget over a printed date
|
|
176
|
+
// would offer an edit that the rendered document does not carry back.
|
|
177
|
+
..if resolved_date == none {
|
|
178
|
+
(date_field: form-field(
|
|
179
|
+
"Ind_" + str(i) + "_Date",
|
|
180
|
+
type: "text",
|
|
181
|
+
width: 1in,
|
|
182
|
+
height: body_font_size,
|
|
183
|
+
field: card.at("$path") + "date",
|
|
184
|
+
))
|
|
185
|
+
},
|
|
186
|
+
..if card.action != "" { (action: card.action) },
|
|
187
|
+
approval_authority: i == last_indorsement_index,
|
|
124
188
|
body_content,
|
|
125
189
|
)
|
|
126
190
|
}
|