1use std::collections::BTreeMap;
2
3use ecow::EcoString;
4use typst_syntax::package::{
5 PackageInfo, PackageManifest, PackageVersion, TemplateInfo, ToolInfo, UnknownFields,
6 VersionBound,
7};
8
9#[derive(Debug, Clone)]
11pub struct PackageManifestBuilder {
12 pub package: PackageInfoBuilder,
13 pub template: Option<TemplateInfoBuilder>,
14 pub tool: ToolInfoBuilder,
15}
16
17impl Default for PackageManifestBuilder {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl PackageManifestBuilder {
24 pub fn new() -> Self {
25 Self {
26 package: PackageInfoBuilder::new(),
27 template: None,
28 tool: ToolInfoBuilder::new(),
29 }
30 }
31
32 pub fn package<T: Into<PackageInfoBuilder>>(&mut self, value: T) -> &mut Self {
33 self.package = value.into();
34 self
35 }
36
37 pub fn template<T: Into<TemplateInfoBuilder>>(&mut self, value: T) -> &mut Self {
38 self.template = Some(value.into());
39 self
40 }
41
42 pub fn tool<T: Into<ToolInfoBuilder>>(&mut self, value: T) -> &mut Self {
43 self.tool = value.into();
44 self
45 }
46
47 pub fn build(&self) -> PackageManifest {
48 self.clone().into()
49 }
50}
51
52#[derive(Debug, Clone)]
54pub struct PackageInfoBuilder {
55 pub name: EcoString,
56 pub version: PackageVersion,
57 pub entrypoint: EcoString,
58 pub authors: Vec<EcoString>,
59 pub license: Option<EcoString>,
60 pub description: Option<EcoString>,
61 pub homepage: Option<EcoString>,
62 pub repository: Option<EcoString>,
63 pub keywords: Vec<EcoString>,
64 pub categories: Vec<EcoString>,
65 pub disciplines: Vec<EcoString>,
66 pub compiler: Option<VersionBound>,
67 pub exclude: Vec<EcoString>,
68}
69
70impl From<PackageManifest> for PackageManifestBuilder {
71 fn from(value: PackageManifest) -> Self {
72 Self {
73 package: value.package.into(),
74 template: value.template.map(Into::into),
75 tool: value.tool.into(),
76 }
77 }
78}
79
80impl From<PackageManifestBuilder> for PackageManifest {
81 fn from(value: PackageManifestBuilder) -> Self {
82 Self {
83 package: value.package.into(),
84 template: value.template.map(Into::into),
85 tool: value.tool.into(),
86 unknown_fields: UnknownFields::new(),
87 }
88 }
89}
90
91const PACKAGE_INFO_VERSION_DEFAULT: PackageVersion = PackageVersion {
92 major: 0,
93 minor: 1,
94 patch: 0,
95};
96const PACKAGE_INFO_NAME_DEFAULT: &str = "my-package";
97const PACKAGE_INFO_ENTRYPOINT_DEFAULT: &str = "src/lib.typ";
98
99impl Default for PackageInfoBuilder {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105impl PackageInfoBuilder {
106 pub fn new() -> Self {
107 Self {
108 name: PACKAGE_INFO_NAME_DEFAULT.into(),
109 version: PACKAGE_INFO_VERSION_DEFAULT,
110 entrypoint: PACKAGE_INFO_ENTRYPOINT_DEFAULT.into(),
111 authors: vec![],
112 license: None,
113 description: None,
114 homepage: None,
115 repository: None,
116 keywords: vec![],
117 categories: vec![],
118 disciplines: vec![],
119 compiler: None,
120 exclude: vec![],
121 }
122 }
123
124 pub fn name<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
125 self.name = value.into();
126 self
127 }
128
129 pub fn version<T: Into<PackageVersion>>(&mut self, value: T) -> &mut Self {
130 self.version = value.into();
131 self
132 }
133
134 pub fn entrypoint<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
135 self.entrypoint = value.into();
136 self
137 }
138
139 pub fn authors<T, I>(&mut self, value: I) -> &mut Self
140 where
141 T: Into<EcoString>,
142 I: IntoIterator<Item = T>,
143 {
144 self.authors = value.into_iter().map(Into::into).collect();
145 self
146 }
147
148 pub fn license<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
149 self.license = Some(value.into());
150 self
151 }
152
153 pub fn description<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
154 self.description = Some(value.into());
155 self
156 }
157
158 pub fn homepage<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
159 self.homepage = Some(value.into());
160 self
161 }
162
163 pub fn repository<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
164 self.repository = Some(value.into());
165 self
166 }
167
168 pub fn keywords<T, I>(&mut self, value: I) -> &mut Self
169 where
170 T: Into<EcoString>,
171 I: IntoIterator<Item = T>,
172 {
173 self.keywords = value.into_iter().map(Into::into).collect();
174 self
175 }
176
177 pub fn categories<T, I>(&mut self, value: I) -> &mut Self
178 where
179 T: Into<EcoString>,
180 I: IntoIterator<Item = T>,
181 {
182 self.categories = value.into_iter().map(Into::into).collect();
183 self
184 }
185
186 pub fn disciplines<T, I>(&mut self, value: I) -> &mut Self
187 where
188 T: Into<EcoString>,
189 I: IntoIterator<Item = T>,
190 {
191 self.disciplines = value.into_iter().map(Into::into).collect();
192 self
193 }
194
195 pub fn compiler<T: Into<VersionBound>>(&mut self, value: T) -> &mut Self {
196 self.compiler = Some(value.into());
197 self
198 }
199
200 pub fn exclude<T, I>(&mut self, value: I) -> &mut Self
201 where
202 T: Into<EcoString>,
203 I: IntoIterator<Item = T>,
204 {
205 self.exclude = value.into_iter().map(Into::into).collect();
206 self
207 }
208
209 pub fn build(&self) -> PackageInfo {
210 self.clone().into()
211 }
212}
213
214impl From<PackageInfo> for PackageInfoBuilder {
215 fn from(value: PackageInfo) -> Self {
216 Self {
217 name: value.name,
218 version: value.version,
219 entrypoint: value.entrypoint,
220 authors: value.authors,
221 license: value.license,
222 description: value.description,
223 homepage: value.homepage,
224 repository: value.repository,
225 keywords: value.keywords,
226 categories: value.categories,
227 disciplines: value.disciplines,
228 compiler: value.compiler,
229 exclude: value.exclude,
230 }
231 }
232}
233
234impl From<PackageInfoBuilder> for PackageInfo {
235 fn from(value: PackageInfoBuilder) -> Self {
236 Self {
237 name: value.name,
238 version: value.version,
239 entrypoint: value.entrypoint,
240 authors: value.authors,
241 license: value.license,
242 description: value.description,
243 homepage: value.homepage,
244 repository: value.repository,
245 keywords: value.keywords,
246 categories: value.categories,
247 disciplines: value.disciplines,
248 compiler: value.compiler,
249 exclude: value.exclude,
250 unknown_fields: UnknownFields::new(),
251 }
252 }
253}
254
255const TEMPLATE_INFO_PATH_DEFAULT: &str = "template";
256const TEMPLATE_INFO_ENTRYPOINT_DEFAULT: &str = "main.typ";
257
258#[derive(Debug, Clone)]
260pub struct TemplateInfoBuilder {
261 path: EcoString,
262 entrypoint: EcoString,
263 thumbnail: Option<EcoString>,
264}
265
266impl Default for TemplateInfoBuilder {
267 fn default() -> Self {
268 Self::new()
269 }
270}
271
272impl TemplateInfoBuilder {
273 pub fn new() -> Self {
274 Self {
275 path: TEMPLATE_INFO_PATH_DEFAULT.into(),
276 entrypoint: TEMPLATE_INFO_ENTRYPOINT_DEFAULT.into(),
277 thumbnail: None,
278 }
279 }
280
281 pub fn path<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
282 self.path = value.into();
283 self
284 }
285
286 pub fn entrypoint<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
287 self.entrypoint = value.into();
288 self
289 }
290
291 pub fn thumbnail<T: Into<EcoString>>(&mut self, value: T) -> &mut Self {
292 self.thumbnail = Some(value.into());
293 self
294 }
295
296 pub fn build(&self) -> TemplateInfo {
297 self.clone().into()
298 }
299}
300
301impl From<TemplateInfo> for TemplateInfoBuilder {
302 fn from(value: TemplateInfo) -> Self {
303 Self {
304 path: value.path,
305 entrypoint: value.entrypoint,
306 thumbnail: value.thumbnail,
307 }
308 }
309}
310
311impl From<TemplateInfoBuilder> for TemplateInfo {
312 fn from(value: TemplateInfoBuilder) -> Self {
313 Self {
314 path: value.path,
315 entrypoint: value.entrypoint,
316 thumbnail: value.thumbnail,
317 unknown_fields: UnknownFields::new(),
318 }
319 }
320}
321
322#[derive(Debug, Clone)]
324pub struct ToolInfoBuilder {
325 pub sections: BTreeMap<EcoString, toml::Table>,
326}
327
328impl Default for ToolInfoBuilder {
329 fn default() -> Self {
330 Self::new()
331 }
332}
333
334impl ToolInfoBuilder {
335 pub fn new() -> Self {
336 Self {
337 sections: BTreeMap::new(),
338 }
339 }
340
341 pub fn section<T: Into<BTreeMap<EcoString, toml::Table>>>(mut self, value: T) -> Self {
342 self.sections = value.into();
343 self
344 }
345
346 pub fn with_section<K: Into<EcoString>, V: Into<toml::Table>>(
347 mut self,
348 key: K,
349 val: V,
350 ) -> Self {
351 self.sections.insert(key.into(), val.into());
352 self
353 }
354
355 pub fn build(&self) -> ToolInfo {
356 self.clone().into()
357 }
358}
359
360impl From<ToolInfo> for ToolInfoBuilder {
361 fn from(value: ToolInfo) -> Self {
362 Self {
363 sections: value.sections,
364 }
365 }
366}
367
368impl From<ToolInfoBuilder> for ToolInfo {
369 fn from(value: ToolInfoBuilder) -> Self {
370 Self {
371 sections: value.sections,
372 }
373 }
374}