Repository navigation
Expand file tree
/
Copy pathtemplate.typ
More file actions
178 lines (153 loc) · 4.81 KB
/
Copy pathtemplate.typ
File metadata and controls
178 lines (153 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#import "@preview/dashy-todo:0.1.3": todo
#let resolve_update_date(fallback: "2026年1月28日") = sys.inputs.at(
"update-date",
default: fallback,
)
// 文档模板函数,接受可配置参数
#let doc-config(
header-title: "LightFin INAV 飞控文档",
version: "v1.0",
) = {
// 全局文本设置
set text(
font: ("Noto Sans", "Noto Sans CJK SC"),
size: 11pt,
lang: "zh",
region: "cn",
)
// 段落设置
set par(leading: 0.8em, spacing: 1.2em)
// 页面设置
set page(
paper: "a4",
margin: (x: 2.5cm, y: 2.5cm),
header: context {
if counter(page).get().first() > 1 [
#set text(8pt, gray)
#grid(
columns: (1fr, 1fr),
[#header-title],
align(right)[版本: #version]
)
#v(-0.5em)
#line(length: 100%, stroke: 0.5pt + gray)
]
},
footer: context [
#align(center, text(9pt, gray)[第 #counter(page).display() 页])
],
)
// 标题设置
set heading(numbering: "1.1")
show heading: set block(above: 1.2em, below: 0.6em)
show outline.entry: set par(leading: 1.2em)
}
// 辅助函数:绘制占位/实物图
#let placeholder(caption, img_path: none, height: 10em) = figure(
if img_path != none {
image(img_path, width: 100%)
} else {
rect(width: 100%, height: height, stroke: 1pt + navy, fill: luma(250), radius: 4pt)[
#align(center + horizon)[
#text(gray, size: 14pt)[#caption] \
#v(0.5em)
#text(gray, size: 9pt)[请在此替换为实物照片、PCB 截图或软件界面]
]
]
},
caption: caption,
)
#let trimmed-image = (path, trim: (:), alt: none) => context {
let img = image(path)
// Get dimensions of the source image
let dims = measure(img)
layout(size => {
let left = trim.at("left", default: 0.0%)
let right = trim.at("right", default: 0.0%)
let top = trim.at("top", default: 0.0%)
let bottom = trim.at("bottom", default: 0.0%)
let width-rel-trimmed = 100.0% - left - right
let height-rel-trimmed = 100.0% - top - bottom
let width-source-trimmed = dims.width * width-rel-trimmed
let height-source-trimmed = dims.height * height-rel-trimmed
// Aspect ratio h/w of the layout (available space)
let aspect-height-layout = size.height / size.width
// Aspect ratio h/w of the trimmed image
let aspect-height-trimmed = height-source-trimmed / width-source-trimmed
let width-final-trimmed = none
let height-final-trimmed = none
// Compute final size of trimmed image
// by expanding along dimension that first hits the layout constraints
if aspect-height-layout >= aspect-height-trimmed {
// Expand width of image
width-final-trimmed = size.width
height-final-trimmed = aspect-height-trimmed * width-final-trimmed
} else {
// Expand height of image
height-final-trimmed = size.height
width-final-trimmed = size.height / aspect-height-trimmed
}
// Compute the hypothetical size of the image without trimming
let width-final-untrimmed = width-final-trimmed / float(width-rel-trimmed)
let height-final-untrimmed = height-final-trimmed / float(height-rel-trimmed)
box(
clip: true,
inset: (
top: -(top * height-final-untrimmed),
bottom: -(bottom * height-final-untrimmed),
left: -(left * width-final-untrimmed),
right: -(right * width-final-untrimmed)
),
// TODO: Handle explicit sizing according to a parameter (e.g. don't scale over DPI limits)
image(path, width: width-final-untrimmed, height: height-final-untrimmed, alt: alt)
)
})
}
#let caution(body) = block(
fill: rgb("#fff5f5"),
stroke: (left: 4pt + red),
inset: 12pt,
radius: 4pt,
width: 100%,
[*注意:* #body],
)
#let tip(body) = block(
fill: rgb("#f0f8ff"),
stroke: (left: 4pt + blue),
inset: 12pt,
radius: 4pt,
width: 100%,
[*提示:* #body],
)
// 封面模板函数
#let cover-page(
main-title: "LightFin INAV 飞控文档",
subtitle: "",
doc-version: "v1.0",
update-date: "2026年1月28日",
hardware-info: "适用硬件:LightFin 飞控",
show-product-image: true,
product-image-path: "assets/product-overview.aggressive-plus.jpg",
) = {
align(center + horizon)[
#block(inset: 3em)[
#text(28pt, weight: "bold", fill: navy)[LightFin] \
#v(0.4em)
#text(18pt, weight: "medium")[#main-title] \
#if subtitle != "" [
#v(1.2em)
#text(11pt, gray)[#subtitle]
]
]
#if show-product-image [
#placeholder("产品外观与接口示意图", img_path: product-image-path, height: 15em)
]
#v(1fr)
#text(10pt, gray)[文档版本:#doc-version | 最后更新:#update-date] \
#text(10pt, gray)[#hardware-info]
]
pagebreak()
// 目录
outline(indent: 2em, depth: 2)
pagebreak()
}