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 extension(&self) -> &str {
121 match self {
122 Self::ExportPdf { .. } => "pdf",
123 Self::Preview(..) | Self::ExportSvgHtml { .. } | Self::ExportHtml { .. } => "html",
124 Self::ExportMd { .. } => "md",
125 Self::ExportTeX { .. } => "tex",
126 Self::ExportText { .. } => "txt",
127 Self::ExportSvg { .. } => "svg",
128 Self::ExportPng { .. } => "png",
129 Self::Query(QueryTask {
130 format,
131 output_extension,
132 ..
133 }) => output_extension.as_deref().unwrap_or(format),
134 }
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
140#[serde(rename_all = "kebab-case")]
141pub struct PreviewTask {
142 pub when: TaskWhen,
145}
146
147#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
149#[serde(rename_all = "kebab-case")]
150pub struct ExportTask {
151 pub when: TaskWhen,
153 pub output: Option<PathPattern>,
155 #[serde(skip_serializing_if = "Vec::is_empty", default)]
157 pub transform: Vec<ExportTransform>,
158}
159
160impl ExportTask {
161 pub fn new(when: TaskWhen) -> Self {
163 Self {
164 when,
165 output: None,
166 transform: Vec::new(),
167 }
168 }
169
170 pub fn apply_pretty(&mut self) {
172 self.transform
173 .push(ExportTransform::Pretty { script: None });
174 }
175}
176
177#[derive(Default, Debug, Clone, Serialize, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub enum PageSelection {
181 #[default]
183 First,
184 Merged {
186 gap: Option<String>,
188 },
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
193#[serde(rename_all = "kebab-case")]
194pub enum ExportTransform {
195 Pages {
197 ranges: Vec<Pages>,
199 },
200 Merge {
202 gap: Option<String>,
204 },
205 Script {
207 #[serde(skip_serializing_if = "Option::is_none", default)]
209 script: Option<String>,
210 },
211 Pretty {
213 #[serde(skip_serializing_if = "Option::is_none", default)]
218 script: Option<String>,
219 },
220}
221
222#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
224#[serde(rename_all = "kebab-case")]
225pub struct ExportPdfTask {
226 #[serde(flatten)]
228 pub export: ExportTask,
229 #[serde(skip_serializing_if = "Vec::is_empty", default)]
232 pub pdf_standards: Vec<PdfStandard>,
233 #[serde(skip_serializing_if = "Option::is_none", default)]
237 pub creation_timestamp: Option<i64>,
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
242#[serde(rename_all = "kebab-case")]
243pub struct ExportPngTask {
244 #[serde(flatten)]
246 pub export: ExportTask,
247 pub ppi: Scalar,
249 #[serde(skip_serializing_if = "Option::is_none", default)]
255 pub fill: Option<String>,
256}
257
258#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
260#[serde(rename_all = "kebab-case")]
261pub struct ExportSvgTask {
262 #[serde(flatten)]
264 pub export: ExportTask,
265}
266
267#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
269#[serde(rename_all = "kebab-case")]
270pub struct ExportHtmlTask {
271 #[serde(flatten)]
273 pub export: ExportTask,
274}
275
276#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
278#[serde(rename_all = "kebab-case")]
279pub struct ExportMarkdownTask {
280 pub processor: Option<String>,
282 pub assets_path: Option<PathBuf>,
284 #[serde(flatten)]
286 pub export: ExportTask,
287}
288
289#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
291#[serde(rename_all = "kebab-case")]
292pub struct ExportTeXTask {
293 pub processor: Option<String>,
295 pub assets_path: Option<PathBuf>,
297 #[serde(flatten)]
299 pub export: ExportTask,
300}
301
302#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
304#[serde(rename_all = "kebab-case")]
305pub struct ExportTextTask {
306 #[serde(flatten)]
308 pub export: ExportTask,
309}
310
311#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
313#[serde(rename_all = "kebab-case")]
314pub struct QueryTask {
315 #[serde(flatten)]
317 pub export: ExportTask,
318 pub format: String,
320 pub output_extension: Option<String>,
323 pub selector: String,
325 pub field: Option<String>,
327 pub one: bool,
329}