tytanic_utils/
typst.rs

1use std::collections::BTreeMap;
2
3use ecow::EcoString;
4use typst_syntax::package::{
5    PackageInfo, PackageManifest, PackageVersion, TemplateInfo, ToolInfo, UnknownFields,
6    VersionBound,
7};
8
9/// A builder for [`PackageManifest`].
10#[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/// A builder for [`PackageInfo`].
53#[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/// A builder for [`TemplateInfo`].
259#[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/// A builder for [`ToolInfo`].
323#[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}