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 ExportSvgHtml(ExportHtmlTask),
73 ExportMd(ExportMarkdownTask),
75 ExportTeX(ExportTeXTask),
77 ExportText(ExportTextTask),
79 Query(QueryTask),
81 }
85
86impl ProjectTask {
87 pub fn when(&self) -> Option<&TaskWhen> {
89 Some(match self {
90 Self::Preview(task) => &task.when,
91 Self::ExportPdf(..)
92 | Self::ExportPng(..)
93 | Self::ExportSvg(..)
94 | Self::ExportHtml(..)
95 | Self::ExportSvgHtml(..)
96 | Self::ExportMd(..)
97 | Self::ExportTeX(..)
98 | Self::ExportText(..)
99 | Self::Query(..) => &self.as_export()?.when,
100 })
101 }
102
103 pub fn as_export(&self) -> Option<&ExportTask> {
105 Some(match self {
106 Self::Preview(..) => return None,
107 Self::ExportPdf(task) => &task.export,
108 Self::ExportPng(task) => &task.export,
109 Self::ExportSvg(task) => &task.export,
110 Self::ExportHtml(task) => &task.export,
111 Self::ExportSvgHtml(task) => &task.export,
112 Self::ExportTeX(task) => &task.export,
113 Self::ExportMd(task) => &task.export,
114 Self::ExportText(task) => &task.export,
115 Self::Query(task) => &task.export,
116 })
117 }
118
119 pub fn as_export_mut(&mut self) -> Option<&mut ExportTask> {
121 Some(match self {
122 Self::Preview(..) => return None,
123 Self::ExportPdf(task) => &mut task.export,
124 Self::ExportPng(task) => &mut task.export,
125 Self::ExportSvg(task) => &mut task.export,
126 Self::ExportHtml(task) => &mut task.export,
127 Self::ExportSvgHtml(task) => &mut task.export,
128 Self::ExportTeX(task) => &mut task.export,
129 Self::ExportMd(task) => &mut task.export,
130 Self::ExportText(task) => &mut task.export,
131 Self::Query(task) => &mut task.export,
132 })
133 }
134
135 pub fn extension(&self) -> &str {
137 match self {
138 Self::ExportPdf { .. } => "pdf",
139 Self::Preview(..) | Self::ExportSvgHtml { .. } | Self::ExportHtml { .. } => "html",
140 Self::ExportMd { .. } => "md",
141 Self::ExportTeX { .. } => "tex",
142 Self::ExportText { .. } => "txt",
143 Self::ExportSvg { .. } => "svg",
144 Self::ExportPng { .. } => "png",
145 Self::Query(QueryTask {
146 format,
147 output_extension,
148 ..
149 }) => output_extension.as_deref().unwrap_or(format),
150 }
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
156#[serde(rename_all = "kebab-case")]
157pub struct PreviewTask {
158 pub when: TaskWhen,
161}
162
163#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
165#[serde(rename_all = "kebab-case")]
166pub struct ExportTask {
167 pub when: TaskWhen,
169 pub output: Option<PathPattern>,
171 #[serde(skip_serializing_if = "Vec::is_empty", default)]
173 pub transform: Vec<ExportTransform>,
174}
175
176impl ExportTask {
177 pub fn new(when: TaskWhen) -> Self {
179 Self {
180 when,
181 output: None,
182 transform: Vec::new(),
183 }
184 }
185
186 pub fn apply_pretty(&mut self) {
188 self.transform
189 .push(ExportTransform::Pretty { script: None });
190 }
191}
192
193#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
195#[serde(default)]
196pub struct PageMerge {
197 pub gap: Option<String>,
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
203#[serde(rename_all = "kebab-case")]
204pub enum ExportTransform {
205 Pages {
207 ranges: Vec<Pages>,
209 },
210 Merge {
212 gap: Option<String>,
214 },
215 Script {
217 #[serde(skip_serializing_if = "Option::is_none", default)]
219 script: Option<String>,
220 },
221 Pretty {
223 #[serde(skip_serializing_if = "Option::is_none", default)]
228 script: Option<String>,
229 },
230}
231
232#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
234#[serde(rename_all = "kebab-case")]
235pub struct ExportPdfTask {
236 #[serde(flatten)]
238 pub export: ExportTask,
239 #[serde(skip_serializing_if = "Option::is_none", default)]
241 pub pages: Option<Vec<Pages>>,
242 #[serde(skip_serializing_if = "Vec::is_empty", default)]
245 pub pdf_standards: Vec<PdfStandard>,
246 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
251 pub no_pdf_tags: bool,
252 #[serde(skip_serializing_if = "Option::is_none", default)]
256 pub creation_timestamp: Option<i64>,
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
261#[serde(rename_all = "kebab-case")]
262pub struct ExportPngTask {
263 #[serde(flatten)]
265 pub export: ExportTask,
266 #[serde(skip_serializing_if = "Option::is_none", default)]
268 pub pages: Option<Vec<Pages>>,
269 #[serde(skip_serializing_if = "Option::is_none", default)]
271 pub page_number_template: Option<String>,
272 #[serde(skip_serializing_if = "Option::is_none", default)]
274 pub merge: Option<PageMerge>,
275 pub ppi: Scalar,
277 #[serde(skip_serializing_if = "Option::is_none", default)]
283 pub fill: Option<String>,
284}
285
286#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
288#[serde(rename_all = "kebab-case")]
289pub struct ExportSvgTask {
290 #[serde(flatten)]
292 pub export: ExportTask,
293 #[serde(skip_serializing_if = "Option::is_none", default)]
295 pub page_number_template: Option<String>,
296 #[serde(skip_serializing_if = "Option::is_none", default)]
298 pub pages: Option<Vec<Pages>>,
299 #[serde(skip_serializing_if = "Option::is_none", default)]
301 pub merge: Option<PageMerge>,
302}
303
304#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
306#[serde(rename_all = "kebab-case")]
307pub struct ExportHtmlTask {
308 #[serde(flatten)]
310 pub export: ExportTask,
311}
312
313#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
315#[serde(rename_all = "kebab-case")]
316pub struct ExportMarkdownTask {
317 pub processor: Option<String>,
319 pub assets_path: Option<PathBuf>,
321 #[serde(flatten)]
323 pub export: ExportTask,
324}
325
326#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
328#[serde(rename_all = "kebab-case")]
329pub struct ExportTeXTask {
330 pub processor: Option<String>,
332 pub assets_path: Option<PathBuf>,
334 #[serde(flatten)]
336 pub export: ExportTask,
337}
338
339#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
341#[serde(rename_all = "kebab-case")]
342pub struct ExportTextTask {
343 #[serde(flatten)]
345 pub export: ExportTask,
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
350#[serde(rename_all = "kebab-case")]
351pub struct QueryTask {
352 #[serde(flatten)]
354 pub export: ExportTask,
355 pub format: String,
357 pub output_extension: Option<String>,
360 pub selector: String,
362 pub field: Option<String>,
364 pub one: bool,
366}