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 = "Option::is_none", default)]
250 pub creation_timestamp: Option<i64>,
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
255#[serde(rename_all = "kebab-case")]
256pub struct ExportPngTask {
257 #[serde(flatten)]
259 pub export: ExportTask,
260 #[serde(skip_serializing_if = "Option::is_none", default)]
262 pub pages: Option<Vec<Pages>>,
263 #[serde(skip_serializing_if = "Option::is_none", default)]
265 pub page_number_template: Option<String>,
266 #[serde(skip_serializing_if = "Option::is_none", default)]
268 pub merge: Option<PageMerge>,
269 pub ppi: Scalar,
271 #[serde(skip_serializing_if = "Option::is_none", default)]
277 pub fill: Option<String>,
278}
279
280#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
282#[serde(rename_all = "kebab-case")]
283pub struct ExportSvgTask {
284 #[serde(flatten)]
286 pub export: ExportTask,
287 #[serde(skip_serializing_if = "Option::is_none", default)]
289 pub page_number_template: Option<String>,
290 #[serde(skip_serializing_if = "Option::is_none", default)]
292 pub pages: Option<Vec<Pages>>,
293 #[serde(skip_serializing_if = "Option::is_none", default)]
295 pub merge: Option<PageMerge>,
296}
297
298#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
300#[serde(rename_all = "kebab-case")]
301pub struct ExportHtmlTask {
302 #[serde(flatten)]
304 pub export: ExportTask,
305}
306
307#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
309#[serde(rename_all = "kebab-case")]
310pub struct ExportMarkdownTask {
311 pub processor: Option<String>,
313 pub assets_path: Option<PathBuf>,
315 #[serde(flatten)]
317 pub export: ExportTask,
318}
319
320#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
322#[serde(rename_all = "kebab-case")]
323pub struct ExportTeXTask {
324 pub processor: Option<String>,
326 pub assets_path: Option<PathBuf>,
328 #[serde(flatten)]
330 pub export: ExportTask,
331}
332
333#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
335#[serde(rename_all = "kebab-case")]
336pub struct ExportTextTask {
337 #[serde(flatten)]
339 pub export: ExportTask,
340}
341
342#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
344#[serde(rename_all = "kebab-case")]
345pub struct QueryTask {
346 #[serde(flatten)]
348 pub export: ExportTask,
349 pub format: String,
351 pub output_extension: Option<String>,
354 pub selector: String,
356 pub field: Option<String>,
358 pub one: bool,
360}