@tonguetoquill/collection 0.2.3 → 0.2.5-beta.1
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 +201 -201
- package/README.md +39 -39
- package/index.d.ts +2 -2
- package/index.js +8 -8
- package/package.json +41 -41
- package/quills/af4141/0.1.0/Quill.yaml +88 -88
- package/quills/af4141/0.1.0/design/TASK.md +19 -19
- package/quills/af4141/0.1.0/example.md +35 -35
- package/quills/af4141/0.1.0/packages/typst-af4141/FIELDS.json +3169 -3169
- package/quills/af4141/0.1.0/packages/typst-af4141/form.typ +538 -538
- package/quills/af4141/0.1.0/packages/typst-af4141/lib.typ +227 -227
- package/quills/af4141/0.1.0/packages/typst-af4141/typst.toml +7 -7
- package/quills/af4141/0.1.0/plate.typ +48 -48
- package/quills/classic_resume/0.1.0/Quill.yaml +118 -118
- package/quills/classic_resume/0.1.0/example.md +232 -232
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/LICENSE +21 -21
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/README.md +38 -38
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/src/components.typ +184 -184
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/src/layout.typ +42 -42
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/src/lib.typ +5 -5
- package/quills/classic_resume/0.1.0/packages/ttq-classic-resume/typst.toml +26 -26
- package/quills/classic_resume/0.1.0/plate.typ +44 -44
- package/quills/cmu_letter/0.1.0/.quillignore +30 -30
- package/quills/cmu_letter/0.1.0/Quill.yaml +64 -64
- package/quills/cmu_letter/0.1.0/assets/cmu-wordmark.svg +174 -174
- package/quills/cmu_letter/0.1.0/example.md +30 -30
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/LICENSE +21 -21
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/fonts/README.txt +100 -100
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/backmatter.typ +13 -13
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/config.typ +39 -39
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/frontmatter.typ +72 -72
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/lib.typ +47 -47
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/mainmatter.typ +42 -42
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/primitives.typ +70 -70
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/src/utils.typ +85 -85
- package/quills/cmu_letter/0.1.0/packages/tonguetoquill-cmu-letter/typst.toml +17 -17
- package/quills/cmu_letter/0.1.0/plate.typ +19 -19
- package/quills/daf4392/0.1.0/Quill.yaml +110 -0
- package/quills/daf4392/0.1.0/assets/arimo-v35-latin-700.ttf +0 -0
- package/quills/daf4392/0.1.0/assets/arimo-v35-latin-700italic.ttf +0 -0
- package/quills/daf4392/0.1.0/assets/arimo-v35-latin-italic.ttf +0 -0
- package/quills/daf4392/0.1.0/assets/arimo-v35-latin-regular.ttf +0 -0
- package/quills/daf4392/0.1.0/assets/page1.png +0 -0
- package/quills/daf4392/0.1.0/example.md +33 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/FIELDS.json +9 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/form.typ +14 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/lib.typ +227 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/out/debug.typ +4 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/out/example.typ +4 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/page1.png +0 -0
- package/quills/daf4392/0.1.0/packages/daf4392page2_pkg/typst.toml +7 -0
- package/quills/daf4392/0.1.0/plate.typ +60 -0
- package/quills/taro/0.1.0/Quill.yaml +29 -29
- package/quills/taro/0.1.0/example.md +26 -26
- package/quills/taro/0.1.0/plate.typ +31 -31
- package/quills/usaf_memo/0.1.0/.quillignore +30 -30
- package/quills/usaf_memo/0.1.0/Quill.yaml +209 -209
- package/quills/usaf_memo/0.1.0/example.md +54 -54
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/LICENSE +21 -21
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/LICENSE +93 -93
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/LICENSE.md +79 -79
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/GNU General Public License.txt +339 -339
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/backmatter.typ +28 -28
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/body.typ +332 -332
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/config.typ +63 -63
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/frontmatter.typ +114 -114
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +118 -118
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/lib.typ +55 -55
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/mainmatter.typ +32 -32
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +272 -272
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/src/utils.typ +377 -377
- package/quills/usaf_memo/0.1.0/packages/tonguetoquill-usaf-memo/typst.toml +16 -16
- package/quills/usaf_memo/0.1.0/plate.typ +74 -74
- package/quills/usaf_memo/0.2.0/.quillignore +30 -30
- package/quills/usaf_memo/0.2.0/Quill.yaml +219 -219
- package/quills/usaf_memo/0.2.0/example.md +55 -55
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/.gitignore +6 -6
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/LICENSE +21 -21
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/Cinzel/LICENSE +93 -93
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/CopperplateCC/LICENSE.md +79 -79
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/fonts/NimbusRomanNo9L/GNU General Public License.txt +339 -339
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/backmatter.typ +28 -28
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/body.typ +333 -333
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/config.typ +64 -64
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/frontmatter.typ +114 -114
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/indorsement.typ +118 -118
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/lib.typ +55 -55
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/mainmatter.typ +32 -32
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/primitives.typ +293 -293
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/src/utils.typ +374 -374
- package/quills/usaf_memo/0.2.0/packages/tonguetoquill-usaf-memo/typst.toml +27 -27
- package/quills/usaf_memo/0.2.0/plate.typ +75 -75
- package/templates/af4141.md +88 -88
- package/templates/cmu_letter_template.md +37 -37
- package/templates/daf4392.md +33 -0
- package/templates/loc.md +78 -78
- package/templates/pass_request.md +43 -43
- package/templates/rebuttal.md +55 -55
- package/templates/taro.md +26 -26
- package/templates/templates.json +55 -49
- package/templates/usaf_template.md +23 -23
- package/templates/ussf_template.md +29 -29
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
// config.typ: Configuration constants and defaults for USAF memorandum template
|
|
2
|
-
//
|
|
3
|
-
// This module defines core configuration values that implement AFH 33-337 Chapter 14
|
|
4
|
-
// formatting requirements for official USAF memorandums.
|
|
5
|
-
|
|
6
|
-
// =============================================================================
|
|
7
|
-
// SPACING CONSTANTS
|
|
8
|
-
// =============================================================================
|
|
9
|
-
// AFH 33-337 specifies precise spacing requirements throughout Chapter 14
|
|
10
|
-
|
|
11
|
-
#let spacing = (
|
|
12
|
-
line: .5em, // Internal line spacing for readability
|
|
13
|
-
line-height: .7em, // Base line height for spacing calculations
|
|
14
|
-
tab: 0.5in, // Tab stop for multi-column recipient alignment
|
|
15
|
-
margin: 1in, // AFH 33-337 §4: "Use 1-inch margins on the left, right and bottom"
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
// =============================================================================
|
|
19
|
-
// TYPOGRAPHY DEFAULTS
|
|
20
|
-
// =============================================================================
|
|
21
|
-
// AFH 33-337 §5: "Use 12 point Times New Roman font for text"
|
|
22
|
-
|
|
23
|
-
#let DEFAULT_LETTERHEAD_FONTS = ("Copperplate CC",)
|
|
24
|
-
#let DEFAULT_BODY_FONTS = ("times new roman", "NimbusRomNo9L") // AFH 33-337 §5: Times New Roman required
|
|
25
|
-
#let LETTERHEAD_COLOR = rgb("#000099") // Standard USAF blue for letterhead
|
|
26
|
-
|
|
27
|
-
// =============================================================================
|
|
28
|
-
// PARAGRAPH CONFIGURATION
|
|
29
|
-
// =============================================================================
|
|
30
|
-
// AFH 33-337 "The Text of the Official Memorandum" §2:
|
|
31
|
-
// "Number and letter each paragraph and subparagraph"
|
|
32
|
-
// Hierarchical numbering: 1., a., (1), (a), etc.
|
|
33
|
-
|
|
34
|
-
#let paragraph-config = (
|
|
35
|
-
counter-prefix: "par-counter-",
|
|
36
|
-
// AFH 33-337 §2: Hierarchical paragraph numbering format
|
|
37
|
-
// Level 0: 1., 2., 3. | Level 1: a., b., c. | Level 2: (1), (2), (3) | Level 3: (a), (b), (c)
|
|
38
|
-
numbering-formats: ("1.", "a.", "(1)", "(a)", n => underline(str(n)), n => underline(str(n))),
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
// =============================================================================
|
|
42
|
-
// COUNTERS
|
|
43
|
-
// =============================================================================
|
|
44
|
-
|
|
45
|
-
#let counters = (
|
|
46
|
-
indorsement: counter("indorsement"),
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
// =============================================================================
|
|
50
|
-
// CLASSIFICATION COLORS
|
|
51
|
-
// =============================================================================
|
|
52
|
-
// AFH 33-337 §3: "Follow AFI 31-401, Information Security Program Management,
|
|
53
|
-
// applicable executive orders and DoD guidance for the necessary markings on
|
|
54
|
-
// classified correspondence."
|
|
55
|
-
// Color values follow DoD standard classification marking colors
|
|
56
|
-
// Source: https://security.stackexchange.com/questions/161829
|
|
57
|
-
|
|
58
|
-
#let CLASSIFICATION_COLORS = (
|
|
59
|
-
"UNCLASSIFIED": rgb(0, 122, 51), // Forest green (#007A33)
|
|
60
|
-
"CONFIDENTIAL": rgb(0, 51, 160), // Deep blue (#0033A0)
|
|
61
|
-
"SECRET": rgb(200, 16, 46), // Crimson red (#C8102E)
|
|
62
|
-
"TOP SECRET": rgb(255, 103, 31), // Burnt orange (#FF671F)
|
|
63
|
-
)
|
|
1
|
+
// config.typ: Configuration constants and defaults for USAF memorandum template
|
|
2
|
+
//
|
|
3
|
+
// This module defines core configuration values that implement AFH 33-337 Chapter 14
|
|
4
|
+
// formatting requirements for official USAF memorandums.
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// SPACING CONSTANTS
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// AFH 33-337 specifies precise spacing requirements throughout Chapter 14
|
|
10
|
+
|
|
11
|
+
#let spacing = (
|
|
12
|
+
line: .5em, // Internal line spacing for readability
|
|
13
|
+
line-height: .7em, // Base line height for spacing calculations
|
|
14
|
+
tab: 0.5in, // Tab stop for multi-column recipient alignment
|
|
15
|
+
margin: 1in, // AFH 33-337 §4: "Use 1-inch margins on the left, right and bottom"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// TYPOGRAPHY DEFAULTS
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// AFH 33-337 §5: "Use 12 point Times New Roman font for text"
|
|
22
|
+
|
|
23
|
+
#let DEFAULT_LETTERHEAD_FONTS = ("Copperplate CC",)
|
|
24
|
+
#let DEFAULT_BODY_FONTS = ("times new roman", "NimbusRomNo9L") // AFH 33-337 §5: Times New Roman required
|
|
25
|
+
#let LETTERHEAD_COLOR = rgb("#000099") // Standard USAF blue for letterhead
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// PARAGRAPH CONFIGURATION
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// AFH 33-337 "The Text of the Official Memorandum" §2:
|
|
31
|
+
// "Number and letter each paragraph and subparagraph"
|
|
32
|
+
// Hierarchical numbering: 1., a., (1), (a), etc.
|
|
33
|
+
|
|
34
|
+
#let paragraph-config = (
|
|
35
|
+
counter-prefix: "par-counter-",
|
|
36
|
+
// AFH 33-337 §2: Hierarchical paragraph numbering format
|
|
37
|
+
// Level 0: 1., 2., 3. | Level 1: a., b., c. | Level 2: (1), (2), (3) | Level 3: (a), (b), (c)
|
|
38
|
+
numbering-formats: ("1.", "a.", "(1)", "(a)", n => underline(str(n)), n => underline(str(n))),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// COUNTERS
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
#let counters = (
|
|
46
|
+
indorsement: counter("indorsement"),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// CLASSIFICATION COLORS
|
|
51
|
+
// =============================================================================
|
|
52
|
+
// AFH 33-337 §3: "Follow AFI 31-401, Information Security Program Management,
|
|
53
|
+
// applicable executive orders and DoD guidance for the necessary markings on
|
|
54
|
+
// classified correspondence."
|
|
55
|
+
// Color values follow DoD standard classification marking colors
|
|
56
|
+
// Source: https://security.stackexchange.com/questions/161829
|
|
57
|
+
|
|
58
|
+
#let CLASSIFICATION_COLORS = (
|
|
59
|
+
"UNCLASSIFIED": rgb(0, 122, 51), // Forest green (#007A33)
|
|
60
|
+
"CONFIDENTIAL": rgb(0, 51, 160), // Deep blue (#0033A0)
|
|
61
|
+
"SECRET": rgb(200, 16, 46), // Crimson red (#C8102E)
|
|
62
|
+
"TOP SECRET": rgb(255, 103, 31), // Burnt orange (#FF671F)
|
|
63
|
+
)
|
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
// frontmatter.typ: Frontmatter show rule for USAF memorandum
|
|
2
|
-
//
|
|
3
|
-
// This module implements the frontmatter (heading section) of a USAF memorandum
|
|
4
|
-
// per AFH 33-337 Chapter 14 "The Heading Section". It handles:
|
|
5
|
-
// - Page setup with proper margins
|
|
6
|
-
// - Letterhead rendering
|
|
7
|
-
// - Date, MEMORANDUM FOR, FROM, SUBJECT, and References placement
|
|
8
|
-
// - Classification markings in headers/footers
|
|
9
|
-
|
|
10
|
-
#import "primitives.typ": *
|
|
11
|
-
|
|
12
|
-
#let frontmatter(
|
|
13
|
-
subject: none,
|
|
14
|
-
memo_for: none,
|
|
15
|
-
memo_from: none,
|
|
16
|
-
date: none,
|
|
17
|
-
references: none,
|
|
18
|
-
letterhead_title: "DEPARTMENT OF THE AIR FORCE",
|
|
19
|
-
letterhead_caption: "[YOUR SQUADRON/UNIT NAME]",
|
|
20
|
-
letterhead_seal: none,
|
|
21
|
-
letterhead_font: DEFAULT_LETTERHEAD_FONTS,
|
|
22
|
-
body_font: DEFAULT_BODY_FONTS,
|
|
23
|
-
font_size: 12pt,
|
|
24
|
-
memo_for_cols: 3,
|
|
25
|
-
classification_level: none,
|
|
26
|
-
footer_tag_line: none,
|
|
27
|
-
auto_numbering: true,
|
|
28
|
-
it,
|
|
29
|
-
) = {
|
|
30
|
-
assert(subject != none, message: "subject is required")
|
|
31
|
-
assert(memo_for != none, message: "memo_for is required")
|
|
32
|
-
assert(memo_from != none, message: "memo_from is required")
|
|
33
|
-
|
|
34
|
-
let actual_date = if date == none { datetime.today() } else { date }
|
|
35
|
-
let classification_color = get-classification-level-color(classification_level)
|
|
36
|
-
|
|
37
|
-
// Document-wide typography settings (inlined from configure())
|
|
38
|
-
set par(leading: spacing.line, spacing: spacing.line, justify: false)
|
|
39
|
-
set block(above: spacing.line, below: 0em, spacing: 0em)
|
|
40
|
-
set text(font: body_font, size: font_size, fallback: true)
|
|
41
|
-
|
|
42
|
-
set page(
|
|
43
|
-
paper: "us-letter",
|
|
44
|
-
// AFH 33-337 §4: "Use 1-inch margins on the left, right and bottom"
|
|
45
|
-
margin: (
|
|
46
|
-
left: spacing.margin,
|
|
47
|
-
right: spacing.margin,
|
|
48
|
-
top: spacing.margin,
|
|
49
|
-
bottom: spacing.margin,
|
|
50
|
-
),
|
|
51
|
-
header: {
|
|
52
|
-
// AFH 33-337 "Page numbering" §12: "The first page of a memorandum is never numbered.
|
|
53
|
-
// Number the succeeding pages starting with page 2. Place page numbers 0.5-inch from
|
|
54
|
-
// the top of the page, flush with the right margin."
|
|
55
|
-
context if counter(page).get().first() > 1 {
|
|
56
|
-
place(
|
|
57
|
-
dy: +.5in,
|
|
58
|
-
block(
|
|
59
|
-
width: 100%,
|
|
60
|
-
align(right, text(12pt)[#counter(page).display()]),
|
|
61
|
-
),
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if classification_level != none {
|
|
66
|
-
place(
|
|
67
|
-
top + center,
|
|
68
|
-
dy: 0.375in,
|
|
69
|
-
text(12pt, font: DEFAULT_BODY_FONTS, fill: classification_color)[#strong(classification_level)],
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
footer: {
|
|
74
|
-
place(
|
|
75
|
-
bottom + center,
|
|
76
|
-
dy: -.375in,
|
|
77
|
-
text(12pt, font: DEFAULT_BODY_FONTS, fill: classification_color)[#strong(classification_level)],
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
if not falsey(footer_tag_line) {
|
|
81
|
-
place(
|
|
82
|
-
bottom + center,
|
|
83
|
-
dy: -0.625in,
|
|
84
|
-
align(center)[
|
|
85
|
-
#text(fill: LETTERHEAD_COLOR, font: "cinzel", size: 15pt)[#footer_tag_line]
|
|
86
|
-
],
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
render-letterhead(letterhead_title, letterhead_caption, letterhead_seal, letterhead_font)
|
|
93
|
-
|
|
94
|
-
// AFH 33-337 "Date": "Place the date 1 inch from the right edge, 1.75 inches from the top"
|
|
95
|
-
// Since we have a 1-inch top margin, we need (1.75in - margin) vertical space
|
|
96
|
-
v(1.75in - spacing.margin)
|
|
97
|
-
|
|
98
|
-
render-date-section(actual_date)
|
|
99
|
-
render-for-section(memo_for, memo_for_cols)
|
|
100
|
-
render-from-section(memo_from)
|
|
101
|
-
render-subject-section(subject)
|
|
102
|
-
render-references-section(references)
|
|
103
|
-
|
|
104
|
-
metadata((
|
|
105
|
-
subject: subject,
|
|
106
|
-
original_date: actual_date,
|
|
107
|
-
original_from: first-or-value(memo_from),
|
|
108
|
-
body_font: body_font,
|
|
109
|
-
font_size: font_size,
|
|
110
|
-
auto_numbering: auto_numbering,
|
|
111
|
-
))
|
|
112
|
-
|
|
113
|
-
it
|
|
114
|
-
}
|
|
1
|
+
// frontmatter.typ: Frontmatter show rule for USAF memorandum
|
|
2
|
+
//
|
|
3
|
+
// This module implements the frontmatter (heading section) of a USAF memorandum
|
|
4
|
+
// per AFH 33-337 Chapter 14 "The Heading Section". It handles:
|
|
5
|
+
// - Page setup with proper margins
|
|
6
|
+
// - Letterhead rendering
|
|
7
|
+
// - Date, MEMORANDUM FOR, FROM, SUBJECT, and References placement
|
|
8
|
+
// - Classification markings in headers/footers
|
|
9
|
+
|
|
10
|
+
#import "primitives.typ": *
|
|
11
|
+
|
|
12
|
+
#let frontmatter(
|
|
13
|
+
subject: none,
|
|
14
|
+
memo_for: none,
|
|
15
|
+
memo_from: none,
|
|
16
|
+
date: none,
|
|
17
|
+
references: none,
|
|
18
|
+
letterhead_title: "DEPARTMENT OF THE AIR FORCE",
|
|
19
|
+
letterhead_caption: "[YOUR SQUADRON/UNIT NAME]",
|
|
20
|
+
letterhead_seal: none,
|
|
21
|
+
letterhead_font: DEFAULT_LETTERHEAD_FONTS,
|
|
22
|
+
body_font: DEFAULT_BODY_FONTS,
|
|
23
|
+
font_size: 12pt,
|
|
24
|
+
memo_for_cols: 3,
|
|
25
|
+
classification_level: none,
|
|
26
|
+
footer_tag_line: none,
|
|
27
|
+
auto_numbering: true,
|
|
28
|
+
it,
|
|
29
|
+
) = {
|
|
30
|
+
assert(subject != none, message: "subject is required")
|
|
31
|
+
assert(memo_for != none, message: "memo_for is required")
|
|
32
|
+
assert(memo_from != none, message: "memo_from is required")
|
|
33
|
+
|
|
34
|
+
let actual_date = if date == none { datetime.today() } else { date }
|
|
35
|
+
let classification_color = get-classification-level-color(classification_level)
|
|
36
|
+
|
|
37
|
+
// Document-wide typography settings (inlined from configure())
|
|
38
|
+
set par(leading: spacing.line, spacing: spacing.line, justify: false)
|
|
39
|
+
set block(above: spacing.line, below: 0em, spacing: 0em)
|
|
40
|
+
set text(font: body_font, size: font_size, fallback: true)
|
|
41
|
+
|
|
42
|
+
set page(
|
|
43
|
+
paper: "us-letter",
|
|
44
|
+
// AFH 33-337 §4: "Use 1-inch margins on the left, right and bottom"
|
|
45
|
+
margin: (
|
|
46
|
+
left: spacing.margin,
|
|
47
|
+
right: spacing.margin,
|
|
48
|
+
top: spacing.margin,
|
|
49
|
+
bottom: spacing.margin,
|
|
50
|
+
),
|
|
51
|
+
header: {
|
|
52
|
+
// AFH 33-337 "Page numbering" §12: "The first page of a memorandum is never numbered.
|
|
53
|
+
// Number the succeeding pages starting with page 2. Place page numbers 0.5-inch from
|
|
54
|
+
// the top of the page, flush with the right margin."
|
|
55
|
+
context if counter(page).get().first() > 1 {
|
|
56
|
+
place(
|
|
57
|
+
dy: +.5in,
|
|
58
|
+
block(
|
|
59
|
+
width: 100%,
|
|
60
|
+
align(right, text(12pt)[#counter(page).display()]),
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if classification_level != none {
|
|
66
|
+
place(
|
|
67
|
+
top + center,
|
|
68
|
+
dy: 0.375in,
|
|
69
|
+
text(12pt, font: DEFAULT_BODY_FONTS, fill: classification_color)[#strong(classification_level)],
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
footer: {
|
|
74
|
+
place(
|
|
75
|
+
bottom + center,
|
|
76
|
+
dy: -.375in,
|
|
77
|
+
text(12pt, font: DEFAULT_BODY_FONTS, fill: classification_color)[#strong(classification_level)],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if not falsey(footer_tag_line) {
|
|
81
|
+
place(
|
|
82
|
+
bottom + center,
|
|
83
|
+
dy: -0.625in,
|
|
84
|
+
align(center)[
|
|
85
|
+
#text(fill: LETTERHEAD_COLOR, font: "cinzel", size: 15pt)[#footer_tag_line]
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
render-letterhead(letterhead_title, letterhead_caption, letterhead_seal, letterhead_font)
|
|
93
|
+
|
|
94
|
+
// AFH 33-337 "Date": "Place the date 1 inch from the right edge, 1.75 inches from the top"
|
|
95
|
+
// Since we have a 1-inch top margin, we need (1.75in - margin) vertical space
|
|
96
|
+
v(1.75in - spacing.margin)
|
|
97
|
+
|
|
98
|
+
render-date-section(actual_date)
|
|
99
|
+
render-for-section(memo_for, memo_for_cols)
|
|
100
|
+
render-from-section(memo_from)
|
|
101
|
+
render-subject-section(subject)
|
|
102
|
+
render-references-section(references)
|
|
103
|
+
|
|
104
|
+
metadata((
|
|
105
|
+
subject: subject,
|
|
106
|
+
original_date: actual_date,
|
|
107
|
+
original_from: first-or-value(memo_from),
|
|
108
|
+
body_font: body_font,
|
|
109
|
+
font_size: font_size,
|
|
110
|
+
auto_numbering: auto_numbering,
|
|
111
|
+
))
|
|
112
|
+
|
|
113
|
+
it
|
|
114
|
+
}
|
|
@@ -1,118 +1,118 @@
|
|
|
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
|
-
attachments: none,
|
|
22
|
-
cc: none,
|
|
23
|
-
date: none,
|
|
24
|
-
// Format of indorsement: "standard" (same page), "informal" (no header), or "separate_page" (starts on new page)
|
|
25
|
-
format: "standard",
|
|
26
|
-
// Show the APPROVED / DISAPPROVED action line. Default: false.
|
|
27
|
-
show_action: false,
|
|
28
|
-
// Approval decision: none (no decision), "approved", or "disapproved".
|
|
29
|
-
action: none,
|
|
30
|
-
content,
|
|
31
|
-
) = {
|
|
32
|
-
// Validate format parameter
|
|
33
|
-
assert(
|
|
34
|
-
format in ("standard", "informal", "separate_page"),
|
|
35
|
-
message: "format must be \"standard\", \"informal\", or \"separate_page\"",
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
if format != "informal" {
|
|
39
|
-
assert(from != none, message: "from is required")
|
|
40
|
-
assert(to != none, message: "to is required")
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
let actual_date = if date == none { datetime.today() } else { date }
|
|
45
|
-
let ind_from = first-or-value(from)
|
|
46
|
-
let ind_for = to
|
|
47
|
-
|
|
48
|
-
if format != "informal" {
|
|
49
|
-
// Step the counter BEFORE the context block to avoid read-then-update loop
|
|
50
|
-
counters.indorsement.step()
|
|
51
|
-
|
|
52
|
-
context {
|
|
53
|
-
let config = query(metadata).last().value
|
|
54
|
-
let original_subject = config.subject
|
|
55
|
-
let original_date = config.original_date
|
|
56
|
-
let original_from = config.original_from
|
|
57
|
-
|
|
58
|
-
// Read the counter value (already stepped above)
|
|
59
|
-
let indorsement_number = counters.indorsement.get().at(0, default: 1)
|
|
60
|
-
let indorsement_label = format-indorsement-number(indorsement_number)
|
|
61
|
-
|
|
62
|
-
if format == "separate_page" {
|
|
63
|
-
pagebreak()
|
|
64
|
-
[#indorsement_label to #original_from, #display-date(original_date), #original_subject]
|
|
65
|
-
|
|
66
|
-
blank-line()
|
|
67
|
-
grid(
|
|
68
|
-
columns: (auto, 1fr),
|
|
69
|
-
ind_from, align(right)[#display-date(actual_date)],
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
blank-line()
|
|
73
|
-
grid(
|
|
74
|
-
columns: (auto, auto, 1fr),
|
|
75
|
-
"MEMORANDUM FOR", " ", ind_for,
|
|
76
|
-
)
|
|
77
|
-
} else {
|
|
78
|
-
blank-line()
|
|
79
|
-
grid(
|
|
80
|
-
columns: (auto, 1fr),
|
|
81
|
-
[#indorsement_label, #ind_from], align(right)[#display-date(actual_date)],
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
blank-line()
|
|
85
|
-
grid(
|
|
86
|
-
columns: (auto, auto, 1fr),
|
|
87
|
-
"MEMORANDUM FOR", " ", ind_for,
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
blank-line()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Show action line if explicitly requested or if an action decision is set
|
|
95
|
-
if show_action or action != none {
|
|
96
|
-
render-action-line(action)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
render-body(content)
|
|
100
|
-
|
|
101
|
-
render-signature-block(signature_block, signature-blank-lines: signature_blank_lines)
|
|
102
|
-
|
|
103
|
-
if not falsey(attachments) {
|
|
104
|
-
calculate-backmatter-spacing(true)
|
|
105
|
-
let attachment-count = attachments.len()
|
|
106
|
-
let section-label = if attachment-count == 1 { "Attachment:" } else { str(attachment-count) + " Attachments:" }
|
|
107
|
-
let continuation-label = (
|
|
108
|
-
(if attachment-count == 1 { "Attachment" } else { str(attachment-count) + " Attachments" })
|
|
109
|
-
+ " (listed on next page):"
|
|
110
|
-
)
|
|
111
|
-
render-backmatter-section(attachments, section-label, numbering-style: "1.", continuation-label: continuation-label)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if not falsey(cc) {
|
|
115
|
-
calculate-backmatter-spacing(falsey(attachments))
|
|
116
|
-
render-backmatter-section(cc, "cc:")
|
|
117
|
-
}
|
|
118
|
-
}
|
|
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
|
+
attachments: none,
|
|
22
|
+
cc: none,
|
|
23
|
+
date: none,
|
|
24
|
+
// Format of indorsement: "standard" (same page), "informal" (no header), or "separate_page" (starts on new page)
|
|
25
|
+
format: "standard",
|
|
26
|
+
// Show the APPROVED / DISAPPROVED action line. Default: false.
|
|
27
|
+
show_action: false,
|
|
28
|
+
// Approval decision: none (no decision), "approved", or "disapproved".
|
|
29
|
+
action: none,
|
|
30
|
+
content,
|
|
31
|
+
) = {
|
|
32
|
+
// Validate format parameter
|
|
33
|
+
assert(
|
|
34
|
+
format in ("standard", "informal", "separate_page"),
|
|
35
|
+
message: "format must be \"standard\", \"informal\", or \"separate_page\"",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if format != "informal" {
|
|
39
|
+
assert(from != none, message: "from is required")
|
|
40
|
+
assert(to != none, message: "to is required")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
let actual_date = if date == none { datetime.today() } else { date }
|
|
45
|
+
let ind_from = first-or-value(from)
|
|
46
|
+
let ind_for = to
|
|
47
|
+
|
|
48
|
+
if format != "informal" {
|
|
49
|
+
// Step the counter BEFORE the context block to avoid read-then-update loop
|
|
50
|
+
counters.indorsement.step()
|
|
51
|
+
|
|
52
|
+
context {
|
|
53
|
+
let config = query(metadata).last().value
|
|
54
|
+
let original_subject = config.subject
|
|
55
|
+
let original_date = config.original_date
|
|
56
|
+
let original_from = config.original_from
|
|
57
|
+
|
|
58
|
+
// Read the counter value (already stepped above)
|
|
59
|
+
let indorsement_number = counters.indorsement.get().at(0, default: 1)
|
|
60
|
+
let indorsement_label = format-indorsement-number(indorsement_number)
|
|
61
|
+
|
|
62
|
+
if format == "separate_page" {
|
|
63
|
+
pagebreak()
|
|
64
|
+
[#indorsement_label to #original_from, #display-date(original_date), #original_subject]
|
|
65
|
+
|
|
66
|
+
blank-line()
|
|
67
|
+
grid(
|
|
68
|
+
columns: (auto, 1fr),
|
|
69
|
+
ind_from, align(right)[#display-date(actual_date)],
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
blank-line()
|
|
73
|
+
grid(
|
|
74
|
+
columns: (auto, auto, 1fr),
|
|
75
|
+
"MEMORANDUM FOR", " ", ind_for,
|
|
76
|
+
)
|
|
77
|
+
} else {
|
|
78
|
+
blank-line()
|
|
79
|
+
grid(
|
|
80
|
+
columns: (auto, 1fr),
|
|
81
|
+
[#indorsement_label, #ind_from], align(right)[#display-date(actual_date)],
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
blank-line()
|
|
85
|
+
grid(
|
|
86
|
+
columns: (auto, auto, 1fr),
|
|
87
|
+
"MEMORANDUM FOR", " ", ind_for,
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
blank-line()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Show action line if explicitly requested or if an action decision is set
|
|
95
|
+
if show_action or action != none {
|
|
96
|
+
render-action-line(action)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
render-body(content)
|
|
100
|
+
|
|
101
|
+
render-signature-block(signature_block, signature-blank-lines: signature_blank_lines)
|
|
102
|
+
|
|
103
|
+
if not falsey(attachments) {
|
|
104
|
+
calculate-backmatter-spacing(true)
|
|
105
|
+
let attachment-count = attachments.len()
|
|
106
|
+
let section-label = if attachment-count == 1 { "Attachment:" } else { str(attachment-count) + " Attachments:" }
|
|
107
|
+
let continuation-label = (
|
|
108
|
+
(if attachment-count == 1 { "Attachment" } else { str(attachment-count) + " Attachments" })
|
|
109
|
+
+ " (listed on next page):"
|
|
110
|
+
)
|
|
111
|
+
render-backmatter-section(attachments, section-label, numbering-style: "1.", continuation-label: continuation-label)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if not falsey(cc) {
|
|
115
|
+
calculate-backmatter-spacing(falsey(attachments))
|
|
116
|
+
render-backmatter-section(cc, "cc:")
|
|
117
|
+
}
|
|
118
|
+
}
|