Skip to main content

pptxboss_core/
pml.rs

1//! PresentationML part identities (ECMA-376 Part 1, clause 13; Part 4,
2//! clause 11): content types and relationship types, with both the
3//! Transitional and Strict relationship URIs recognized.
4
5/// Content types of the parts a presentation package contains.
6pub mod content_type {
7    pub const PRESENTATION: &str =
8        "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
9    pub const SLIDESHOW: &str =
10        "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml";
11    pub const TEMPLATE: &str =
12        "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
13    pub const PRESENTATION_MACRO: &str =
14        "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";
15    pub const SLIDESHOW_MACRO: &str =
16        "application/vnd.ms-powerpoint.slideshow.macroEnabled.main+xml";
17    pub const TEMPLATE_MACRO: &str = "application/vnd.ms-powerpoint.template.macroEnabled.main+xml";
18    pub const ADDIN_MACRO: &str = "application/vnd.ms-powerpoint.addin.macroEnabled.main+xml";
19    pub const SLIDE: &str =
20        "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
21    pub const SLIDE_LAYOUT: &str =
22        "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml";
23    pub const SLIDE_MASTER: &str =
24        "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml";
25    pub const NOTES_SLIDE: &str =
26        "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml";
27    pub const NOTES_MASTER: &str =
28        "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml";
29    pub const HANDOUT_MASTER: &str =
30        "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml";
31    pub const PRES_PROPS: &str =
32        "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml";
33    pub const VIEW_PROPS: &str =
34        "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml";
35    pub const TABLE_STYLES: &str =
36        "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml";
37    pub const COMMENT_AUTHORS: &str =
38        "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml";
39    pub const COMMENTS: &str =
40        "application/vnd.openxmlformats-officedocument.presentationml.comments+xml";
41    pub const MODERN_COMMENTS: &str = "application/vnd.ms-powerpoint.comments+xml";
42    pub const AUTHORS: &str = "application/vnd.ms-powerpoint.authors+xml";
43    pub const TAGS: &str = "application/vnd.openxmlformats-officedocument.presentationml.tags+xml";
44    pub const THEME: &str = "application/vnd.openxmlformats-officedocument.theme+xml";
45    pub const THEME_OVERRIDE: &str =
46        "application/vnd.openxmlformats-officedocument.themeOverride+xml";
47    pub const CHART: &str = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml";
48    pub const DIAGRAM_DATA: &str =
49        "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml";
50    pub const EXTENDED_PROPERTIES: &str =
51        "application/vnd.openxmlformats-officedocument.extended-properties+xml";
52    pub const CUSTOM_PROPERTIES: &str =
53        "application/vnd.openxmlformats-officedocument.custom-properties+xml";
54
55    /// Whether `content_type` is one of the Presentation part's main types (13.3.6 plus the macro-enabled forms).
56    pub fn is_presentation_main(content_type: &str) -> bool {
57        [
58            PRESENTATION,
59            SLIDESHOW,
60            TEMPLATE,
61            PRESENTATION_MACRO,
62            SLIDESHOW_MACRO,
63            TEMPLATE_MACRO,
64            ADDIN_MACRO,
65        ]
66        .iter()
67        .any(|known| known.eq_ignore_ascii_case(content_type))
68    }
69}
70
71const TRANSITIONAL_PREFIX: &str =
72    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/";
73const STRICT_PREFIX: &str = "http://purl.oclc.org/ooxml/officeDocument/relationships/";
74const PACKAGE_PREFIX: &str = "http://schemas.openxmlformats.org/package/2006/relationships/";
75const MS_MEDIA: &str = "http://schemas.microsoft.com/office/2007/relationships/media";
76const MS_COMMENTS: &str = "http://schemas.microsoft.com/office/2018/10/relationships/comments";
77const MS_AUTHORS: &str = "http://schemas.microsoft.com/office/2018/10/relationships/authors";
78
79/// The relationship types a reader dispatches on.
80#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
81#[non_exhaustive]
82pub enum RelKind {
83    OfficeDocument,
84    Slide,
85    SlideLayout,
86    SlideMaster,
87    NotesSlide,
88    NotesMaster,
89    HandoutMaster,
90    PresProps,
91    ViewProps,
92    TableStyles,
93    CommentAuthors,
94    Comments,
95    /// The 2018 threaded comments part (`p188:cmLst`).
96    ModernComments,
97    /// The authors part of the 2018 comments.
98    Authors,
99    Tags,
100    Theme,
101    ThemeOverride,
102    Image,
103    Hyperlink,
104    Chart,
105    ChartUserShapes,
106    DiagramData,
107    DiagramLayout,
108    DiagramQuickStyle,
109    DiagramColors,
110    OleObject,
111    Package,
112    Audio,
113    Video,
114    Media,
115    Font,
116    PrinterSettings,
117    VmlDrawing,
118    Control,
119    CustomXml,
120    SlideUpdateInfo,
121    CoreProperties,
122    ExtendedProperties,
123    CustomProperties,
124    Thumbnail,
125    Other,
126}
127
128impl RelKind {
129    /// Classifies a relationship type URI (Transitional or Strict).
130    pub fn of(rel_type: &str) -> RelKind {
131        if let Some(tail) = rel_type
132            .strip_prefix(TRANSITIONAL_PREFIX)
133            .or_else(|| rel_type.strip_prefix(STRICT_PREFIX))
134        {
135            return match tail {
136                "officeDocument" => RelKind::OfficeDocument,
137                "slide" => RelKind::Slide,
138                "slideLayout" => RelKind::SlideLayout,
139                "slideMaster" => RelKind::SlideMaster,
140                "notesSlide" => RelKind::NotesSlide,
141                "notesMaster" => RelKind::NotesMaster,
142                "handoutMaster" => RelKind::HandoutMaster,
143                "presProps" => RelKind::PresProps,
144                "viewProps" => RelKind::ViewProps,
145                "tableStyles" => RelKind::TableStyles,
146                "commentAuthors" => RelKind::CommentAuthors,
147                "comments" => RelKind::Comments,
148                "tags" => RelKind::Tags,
149                "theme" => RelKind::Theme,
150                "themeOverride" => RelKind::ThemeOverride,
151                "image" => RelKind::Image,
152                "hyperlink" => RelKind::Hyperlink,
153                "chart" => RelKind::Chart,
154                "chartUserShapes" => RelKind::ChartUserShapes,
155                "diagramData" => RelKind::DiagramData,
156                "diagramLayout" => RelKind::DiagramLayout,
157                "diagramQuickStyle" => RelKind::DiagramQuickStyle,
158                "diagramColors" => RelKind::DiagramColors,
159                "oleObject" => RelKind::OleObject,
160                "package" => RelKind::Package,
161                "audio" => RelKind::Audio,
162                "video" => RelKind::Video,
163                "font" => RelKind::Font,
164                "printerSettings" => RelKind::PrinterSettings,
165                "vmlDrawing" => RelKind::VmlDrawing,
166                "control" => RelKind::Control,
167                "customXml" => RelKind::CustomXml,
168                "slideUpdateInfo" => RelKind::SlideUpdateInfo,
169                "extended-properties" | "extendedProperties" => RelKind::ExtendedProperties,
170                "custom-properties" | "customProperties" => RelKind::CustomProperties,
171                _ => RelKind::Other,
172            };
173        }
174        if let Some(tail) = rel_type.strip_prefix(PACKAGE_PREFIX) {
175            return match tail {
176                "metadata/core-properties" => RelKind::CoreProperties,
177                "metadata/thumbnail" => RelKind::Thumbnail,
178                _ => RelKind::Other,
179            };
180        }
181        match rel_type {
182            MS_MEDIA => RelKind::Media,
183            MS_COMMENTS => RelKind::ModernComments,
184            MS_AUTHORS => RelKind::Authors,
185            _ => RelKind::Other,
186        }
187    }
188
189    /// The Transitional URI a writer emits for this kind.
190    pub fn uri(self) -> &'static str {
191        match self {
192            RelKind::OfficeDocument => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
193            RelKind::Slide => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide",
194            RelKind::SlideLayout => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout",
195            RelKind::SlideMaster => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster",
196            RelKind::NotesSlide => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide",
197            RelKind::NotesMaster => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster",
198            RelKind::HandoutMaster => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/handoutMaster",
199            RelKind::PresProps => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/presProps",
200            RelKind::ViewProps => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/viewProps",
201            RelKind::TableStyles => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableStyles",
202            RelKind::CommentAuthors => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/commentAuthors",
203            RelKind::Comments => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
204            RelKind::Tags => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tags",
205            RelKind::Theme => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
206            RelKind::ThemeOverride => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/themeOverride",
207            RelKind::Image => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
208            RelKind::Hyperlink => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
209            RelKind::Chart => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
210            RelKind::ChartUserShapes => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartUserShapes",
211            RelKind::DiagramData => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData",
212            RelKind::DiagramLayout => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout",
213            RelKind::DiagramQuickStyle => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle",
214            RelKind::DiagramColors => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors",
215            RelKind::OleObject => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject",
216            RelKind::Package => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package",
217            RelKind::Audio => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/audio",
218            RelKind::Video => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video",
219            RelKind::Media => MS_MEDIA,
220            RelKind::ModernComments => MS_COMMENTS,
221            RelKind::Authors => MS_AUTHORS,
222            RelKind::Font => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
223            RelKind::PrinterSettings => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings",
224            RelKind::VmlDrawing => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
225            RelKind::Control => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/control",
226            RelKind::CustomXml => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
227            RelKind::SlideUpdateInfo => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideUpdateInfo",
228            RelKind::CoreProperties => "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
229            RelKind::ExtendedProperties => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
230            RelKind::CustomProperties => "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties",
231            RelKind::Thumbnail => "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail",
232            RelKind::Other => "",
233        }
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    fn transitional_and_strict_relationship_types_classify_alike() {
243        assert_eq!(
244            RelKind::of(
245                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
246            ),
247            RelKind::Slide
248        );
249        assert_eq!(
250            RelKind::of("http://purl.oclc.org/ooxml/officeDocument/relationships/slide"),
251            RelKind::Slide
252        );
253        assert_eq!(RelKind::of("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"), RelKind::CoreProperties);
254        assert_eq!(RelKind::of("http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"), RelKind::ExtendedProperties);
255        assert_eq!(
256            RelKind::of(
257                "http://purl.oclc.org/ooxml/officeDocument/relationships/extendedProperties"
258            ),
259            RelKind::ExtendedProperties
260        );
261        assert_eq!(RelKind::of(MS_MEDIA), RelKind::Media);
262        assert_eq!(RelKind::of("urn:something"), RelKind::Other);
263        assert_eq!(RelKind::of(RelKind::NotesSlide.uri()), RelKind::NotesSlide);
264    }
265
266    #[test]
267    fn presentation_main_types() {
268        assert!(content_type::is_presentation_main(
269            content_type::PRESENTATION
270        ));
271        assert!(content_type::is_presentation_main(
272            content_type::SLIDESHOW_MACRO
273        ));
274        assert!(content_type::is_presentation_main(
275            &content_type::TEMPLATE.to_ascii_uppercase()
276        ));
277        assert!(!content_type::is_presentation_main(content_type::SLIDE));
278    }
279}