1use std::{hash::Hash, path::PathBuf};
4
5use serde::{Deserialize, Serialize};
6
7use super::{Id, Pages, PathPattern, PdfStandard, Scalar, TaskWhen};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
34#[serde(rename_all = "kebab-case", tag = "type")]
35pub struct ApplyProjectTask {
36 pub id: Id,
38 pub document: Id,
40 #[serde(flatten)]
42 pub task: ProjectTask,
43}
44
45impl ApplyProjectTask {
46 pub fn doc_id(&self) -> &Id {
48 &self.document
49 }
50
51 pub fn id(&self) -> &Id {
53 &self.id
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
59#[serde(rename_all = "kebab-case", tag = "type")]
60pub enum ProjectTask {
61 Preview(PreviewTask),
63 ExportPdf(ExportPdfTask),
65 ExportPng(ExportPngTask),
67 ExportSvg(ExportSvgTask),
69 ExportHtml(ExportHtmlTask),
71 ExportBundle(ExportBundleTask),
73 ExportSvgHtml(ExportHtmlTask),
75 ExportMd(ExportMarkdownTask),
77 ExportTeX(ExportTeXTask),
79 ExportText(ExportTextTask),
81 Query(QueryTask),
83 }
87
88impl ProjectTask {
89 pub fn when(&self) -> Option<&TaskWhen> {
91 Some(match self {
92 Self::Preview(task) => &task.when,
93 Self::ExportPdf(..)
94 | Self::ExportPng(..)
95 | Self::ExportSvg(..)
96 | Self::ExportHtml(..)
97 | Self::ExportBundle(..)
98 | Self::ExportSvgHtml(..)
99 | Self::ExportMd(..)
100 | Self::ExportTeX(..)
101 | Self::ExportText(..)
102 | Self::Query(..) => &self.as_export()?.when,
103 })
104 }
105
106 pub fn as_export(&self) -> Option<&ExportTask> {
108 Some(match self {
109 Self::Preview(..) => return None,
110 Self::ExportPdf(task) => &task.export,
111 Self::ExportPng(task) => &task.export,
112 Self::ExportSvg(task) => &task.export,
113 Self::ExportHtml(task) => &task.export,
114 Self::ExportBundle(task) => &task.export,
115 Self::ExportSvgHtml(task) => &task.export,
116 Self::ExportTeX(task) => &task.export,
117 Self::ExportMd(task) => &task.export,
118 Self::ExportText(task) => &task.export,
119 Self::Query(task) => &task.export,
120 })
121 }
122
123 pub fn as_export_mut(&mut self) -> Option<&mut ExportTask> {
125 Some(match self {
126 Self::Preview(..) => return None,
127 Self::ExportPdf(task) => &mut task.export,
128 Self::ExportPng(task) => &mut task.export,
129 Self::ExportSvg(task) => &mut task.export,
130 Self::ExportHtml(task) => &mut task.export,
131 Self::ExportBundle(task) => &mut task.export,
132 Self::ExportSvgHtml(task) => &mut task.export,
133 Self::ExportTeX(task) => &mut task.export,
134 Self::ExportMd(task) => &mut task.export,
135 Self::ExportText(task) => &mut task.export,
136 Self::Query(task) => &mut task.export,
137 })
138 }
139
140 pub fn extension(&self) -> &str {
142 match self {
143 Self::ExportPdf { .. } => "pdf",
144 Self::Preview(..) | Self::ExportSvgHtml { .. } | Self::ExportHtml { .. } => "html",
145 Self::ExportBundle { .. } => "",
146 Self::ExportMd { .. } => "md",
147 Self::ExportTeX { .. } => "tex",
148 Self::ExportText { .. } => "txt",
149 Self::ExportSvg { .. } => "svg",
150 Self::ExportPng { .. } => "png",
151 Self::Query(QueryTask {
152 format,
153 output_extension,
154 ..
155 }) => output_extension.as_deref().unwrap_or(format),
156 }
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
162#[serde(rename_all = "kebab-case")]
163pub struct PreviewTask {
164 pub when: TaskWhen,
167}
168
169#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
171#[serde(rename_all = "kebab-case")]
172pub struct ExportTask {
173 pub when: TaskWhen,
175 pub output: Option<PathPattern>,
177 #[serde(skip_serializing_if = "Vec::is_empty", default)]
179 pub transform: Vec<ExportTransform>,
180}
181
182impl ExportTask {
183 pub fn new(when: TaskWhen) -> Self {
185 Self {
186 when,
187 output: None,
188 transform: Vec::new(),
189 }
190 }
191
192 pub fn apply_pretty(&mut self) {
194 self.transform
195 .push(ExportTransform::Pretty { script: None });
196 }
197}
198
199#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
201#[serde(default)]
202pub struct PageMerge {
203 pub gap: Option<String>,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
209#[serde(rename_all = "kebab-case")]
210pub enum ExportTransform {
211 Pages {
213 ranges: Vec<Pages>,
215 },
216 Merge {
218 gap: Option<String>,
220 },
221 Script {
223 #[serde(skip_serializing_if = "Option::is_none", default)]
225 script: Option<String>,
226 },
227 Pretty {
229 #[serde(skip_serializing_if = "Option::is_none", default)]
234 script: Option<String>,
235 },
236}
237
238#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
240#[serde(rename_all = "kebab-case")]
241pub struct ExportPdfTask {
242 #[serde(flatten)]
244 pub export: ExportTask,
245 #[serde(skip_serializing_if = "Option::is_none", default)]
247 pub pages: Option<Vec<Pages>>,
248 #[serde(skip_serializing_if = "Vec::is_empty", default)]
251 pub pdf_standards: Vec<PdfStandard>,
252 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
257 pub no_pdf_tags: bool,
258 #[serde(skip_serializing_if = "Option::is_none", default)]
262 pub creation_timestamp: Option<i64>,
263}
264
265#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
267#[serde(rename_all = "kebab-case")]
268pub struct ExportPngTask {
269 #[serde(flatten)]
271 pub export: ExportTask,
272 #[serde(skip_serializing_if = "Option::is_none", default)]
274 pub pages: Option<Vec<Pages>>,
275 #[serde(skip_serializing_if = "Option::is_none", default)]
277 pub page_number_template: Option<String>,
278 #[serde(skip_serializing_if = "Option::is_none", default)]
280 pub merge: Option<PageMerge>,
281 pub ppi: Scalar,
283 #[serde(skip_serializing_if = "Option::is_none", default)]
289 pub fill: Option<String>,
290}
291
292#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
294#[serde(rename_all = "kebab-case")]
295pub struct ExportSvgTask {
296 #[serde(flatten)]
298 pub export: ExportTask,
299 #[serde(skip_serializing_if = "Option::is_none", default)]
301 pub page_number_template: Option<String>,
302 #[serde(skip_serializing_if = "Option::is_none", default)]
304 pub pages: Option<Vec<Pages>>,
305 #[serde(skip_serializing_if = "Option::is_none", default)]
307 pub merge: Option<PageMerge>,
308}
309
310#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
312#[serde(rename_all = "kebab-case")]
313pub struct ExportHtmlTask {
314 #[serde(flatten)]
316 pub export: ExportTask,
317}
318
319#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
321#[serde(rename_all = "kebab-case")]
322pub struct ExportBundleTask {
323 #[serde(flatten)]
325 pub export: ExportTask,
326 #[serde(skip_serializing_if = "Option::is_none", default)]
329 pub pages: Option<Vec<Pages>>,
330 #[serde(skip_serializing_if = "Vec::is_empty", default)]
333 pub pdf_standards: Vec<PdfStandard>,
334 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
336 pub no_pdf_tags: bool,
337 #[serde(skip_serializing_if = "Option::is_none", default)]
339 pub creation_timestamp: Option<i64>,
340 pub ppi: Scalar,
342}
343
344#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
346#[serde(rename_all = "kebab-case")]
347pub struct ExportMarkdownTask {
348 pub processor: Option<String>,
350 pub assets_path: Option<PathBuf>,
352 #[serde(flatten)]
354 pub export: ExportTask,
355}
356
357#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
359#[serde(rename_all = "kebab-case")]
360pub struct ExportTeXTask {
361 pub processor: Option<String>,
363 pub assets_path: Option<PathBuf>,
365 #[serde(flatten)]
367 pub export: ExportTask,
368}
369
370#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
372#[serde(rename_all = "kebab-case")]
373pub struct ExportTextTask {
374 #[serde(flatten)]
376 pub export: ExportTask,
377}
378
379#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
381#[serde(rename_all = "kebab-case")]
382pub struct QueryTask {
383 #[serde(flatten)]
385 pub export: ExportTask,
386 pub format: String,
388 pub output_extension: Option<String>,
391 pub selector: String,
393 pub field: Option<String>,
395 pub one: bool,
397}