spreadsheet_ods/
text.rs

1//! Text is stored as a simple String whenever possible.
2//! When there is a more complex structure, a TextTag is constructed
3//! which mirrors the Xml tree structure.
4//!
5//! For construction of a new TextTag structure a few helper structs are
6//! defined.
7//!
8//! ```
9//! use spreadsheet_ods::text::{TextP, TextTag, MetaAuthorName, MetaCreationDate, TextS};
10//! use spreadsheet_ods::style::ParagraphStyleRef;
11//!
12//! let p1_ref = ParagraphStyleRef::from("p1");
13//!
14//! let txt = TextP::new()
15//!             .style_name(&p1_ref)
16//!             .text("some text")
17//!             .tag(MetaAuthorName::new())
18//!             .tag(TextS::new())
19//!             .tag(MetaCreationDate::new())
20//!             .tag(TextS::new())
21//!             .text("whatever");
22//! println!("{}", txt.into_xmltag());
23//! ```
24//!
25
26use crate::style::{ParagraphStyleRef, TextStyleRef};
27use crate::xmltree::{XmlContent, XmlTag};
28use std::fmt::{Display, Formatter};
29
30/// TextTags are just XmlTags.
31pub type TextTag = XmlTag;
32/// Content of a TextTag is just some XmlContent.
33pub type TextContent = XmlContent;
34
35text_tag!(TextH, "text:h");
36
37// ok text:class-names 19.770.2,
38// ok text:cond-style-name 19.776,
39// ok text:id 19.809.6,
40// ok text:is-list-header 19.816,
41// ok text:outline-level 19.844.4,
42// ok text:restart-numbering 19.857,
43// ok text:start-value 19.868.2,
44// ok text:style-name 19.874.7,
45// ignore xhtml:about 19.905,
46// ignore xhtml:content 19.906,
47// ignore xhtml:datatype 19.907,
48// ignore xhtml:property 19.908
49// ok xml:id 19.914.
50impl TextH {
51    /// Sets class names aka paragraph styles as formatting.
52    pub fn class_names(mut self, class_names: &[&ParagraphStyleRef]) -> Self {
53        let mut buf = String::new();
54        for n in class_names {
55            buf.push_str(n.as_str());
56            buf.push(' ');
57        }
58        self.xml.set_attr("text:class-names", buf);
59        self
60    }
61
62    /// Sets a conditional style.
63    pub fn condstyle_name(mut self, name: &ParagraphStyleRef) -> Self {
64        self.xml
65            .set_attr("text:condstyle-name", name.as_str().to_string());
66        self
67    }
68
69    /// Identifier for a text passage.
70    pub fn id(mut self, id: &str) -> Self {
71        self.xml.set_attr("text:id", id);
72        self
73    }
74
75    /// Styled as list header.
76    pub fn list_header(mut self, lh: bool) -> Self {
77        self.xml.set_attr("text:is-list-header", lh.to_string());
78        self
79    }
80
81    /// Level of the heading.
82    pub fn outline_level(mut self, l: u8) -> Self {
83        self.xml.set_attr("text:outlinelevel", l.to_string());
84        self
85    }
86
87    /// Numbering reset.
88    pub fn restart_numbering(mut self, r: bool) -> Self {
89        self.xml.set_attr("text:restart-numbering", r.to_string());
90        self
91    }
92
93    /// Numbering start value.
94    pub fn start_value(mut self, l: u8) -> Self {
95        self.xml.set_attr("text:start-value", l.to_string());
96        self
97    }
98
99    /// Style
100    pub fn style_name(mut self, name: &ParagraphStyleRef) -> Self {
101        self.xml
102            .set_attr("text:style-name", name.as_str().to_string());
103        self
104    }
105
106    /// xml-id
107    pub fn xml_id(mut self, id: &str) -> Self {
108        self.xml.set_attr("xml:id", id);
109        self
110    }
111}
112
113text_tag!(TextP, "text:p");
114
115// ok text:class-names 19.770.3,
116// ok text:cond-style-name 19.776,
117// ok text:id 19.809.8,
118// ok text:style-name 19.874.29,
119// ignore xhtml:about 19.905,
120// ignore xhtml:content 19.906,
121// ignore xhtml:datatype 19.907,
122// ignore xhtml:property 19.908
123// ok xml:id 19.914.
124impl TextP {
125    /// Sets class names aka paragraph styles as formatting.
126    pub fn class_names(mut self, class_names: &[&ParagraphStyleRef]) -> Self {
127        let mut buf = String::new();
128        for n in class_names {
129            buf.push_str(n.as_str());
130            buf.push(' ');
131        }
132        self.xml.set_attr("text:class-names", buf);
133        self
134    }
135
136    /// Sets a conditional style.
137    pub fn condstyle_name(mut self, name: &ParagraphStyleRef) -> Self {
138        self.xml
139            .set_attr("text:condstyle-name", name.as_str().to_string());
140        self
141    }
142
143    /// Text id for a text passage.
144    pub fn id(mut self, id: &str) -> Self {
145        self.xml.set_attr("text:id", id);
146        self
147    }
148
149    /// Style for this paragraph.
150    pub fn style_name(mut self, name: &ParagraphStyleRef) -> Self {
151        self.xml
152            .set_attr("text:style-name", name.as_str().to_string());
153        self
154    }
155
156    /// xml-id
157    pub fn xml_id(mut self, id: &str) -> Self {
158        self.xml.set_attr("xml:id", id);
159        self
160    }
161}
162
163// The <text:span> element represents the application of a style to the character data of a portion
164// of text. The content of this element is the text which uses that text style.
165//
166// The <text:span> element can be nested.
167//
168// White space characters contained in this element are collapsed.
169text_tag!(TextSpan, "text:span");
170
171// text:class-names 19.770.4 and
172// text:style-name 19.874.33.
173impl TextSpan {
174    /// A text:class-names attribute specifies a white space separated list of text style names.
175    pub fn class_names(mut self, class_names: &[&TextStyleRef]) -> Self {
176        let mut buf = String::new();
177        for n in class_names {
178            buf.push_str(n.as_str());
179            buf.push(' ');
180        }
181        self.xml.set_attr("text:class-names", buf);
182        self
183    }
184
185    /// The text:style-name attribute specifies style for span which shall be a style with family of
186    /// text.
187    /// If both text:style-name and text:class-names are present, the style referenced by the
188    /// text:style-name attribute is treated as the first style in the list in text:class-names.
189    /// Consumers should support the text:class-names attribute and also should preserve it while
190    /// editing.
191    pub fn style_name(mut self, name: &TextStyleRef) -> Self {
192        self.xml
193            .set_attr("text:style-name", name.as_str().to_string());
194        self
195    }
196}
197
198// The <text:a> element represents a hyperlink.
199//
200// The anchor of a hyperlink is composed of the character data contained by the <text:a> element
201// and any of its descendant elements which constitute the character data of the paragraph which
202// contains the <text:a> element. 6.1.1
203text_tag!(TextA, "text:a");
204
205// obsolete office:name 19.376.9,
206// ??? office:target-frame-name 19.381,
207// ??? office:title 19.383,
208// ok text:style-name 19.874.2,
209// ok text:visited-style-name 19.901,
210// ??? xlink:actuate 19.909,
211// ok xlink:href 19.910.33,
212// ??? xlink:show 19.911 and
213// ??? xlink:type 19.913.
214impl TextA {
215    /// The text:style-name attribute specifies a text style for an unvisited hyperlink.
216    pub fn style_name(mut self, style: &TextStyleRef) -> Self {
217        self.xml
218            .set_attr("text:style-name", style.as_str().to_string());
219        self
220    }
221
222    /// The text:visited-style-name attribute specifies a style for a hyperlink that has been visited.
223    pub fn visited_style_name(mut self, style: &TextStyleRef) -> Self {
224        self.xml
225            .set_attr("text:visited-style-name", style.as_str().to_string());
226        self
227    }
228
229    /// href for a link.
230    pub fn href<S: Into<String>>(mut self, uri: S) -> Self {
231        self.xml.set_attr("xlink:href", uri.into());
232        self
233    }
234}
235
236// The <text:s> element is used to represent the [UNICODE] character “ “ (U+0020, SPACE).
237// This element shall be used to represent the second and all following “ “ (U+0020, SPACE)
238// characters in a sequence of “ “ (U+0020, SPACE) characters.
239//
240// Note: It is not an error if the character preceding the element is not a white space character, but it
241// is good practice to use this element only for the second and all following “ “ (U+0020, SPACE)
242// characters in a sequence.
243text_tag!(TextS, "text:s");
244
245// text:c 19.763.
246impl TextS {
247    /// The text:c attribute specifies the number of “ “ (U+0020, SPACE) characters that a <text:s>
248    /// element represents. A missing text:c attribute is interpreted as a single “ “ (U+0020, SPACE)
249    /// character.
250    pub fn count(mut self, count: u32) -> Self {
251        self.xml.set_attr("text:c", count.to_string());
252        self
253    }
254}
255
256// The <text:tab> element represents the [UNICODE] tab character (HORIZONTAL
257// TABULATION, U+0009).
258//
259// A <text:tab> element specifies that content immediately following it
260// should begin at the next tab stop.
261text_tag!(TextTab, "text:tab");
262
263impl TextTab {
264    /// The text:tab-ref attribute contains the number of the tab-stop to which a tab character refers.
265    /// The position 0 marks the start margin of a paragraph.
266    ///
267    /// Note: The text:tab-ref attribute is only a hint to help non-layout oriented consumers to
268    /// determine the tab/tab-stop association. Layout oriented consumers should determine the tab
269    /// positions based on the style information.
270    pub fn tab_ref(mut self, tab_ref: u32) -> Self {
271        self.xml.set_attr("text:tab-ref", tab_ref.to_string());
272        self
273    }
274}
275
276// The <text:soft-page-break> element represents a soft page break within or between
277// paragraph elements. As a child element of a <table:table> element it represents a soft page break between two
278// table rows. It may appear in front of a <table:table-row> element.
279text_tag!(SoftPageBreak, "text:soft-page-break");
280
281// The <text:date> element displays a date, by default this is the current date. The date can be
282// adjusted to display a date other than the current date.
283text_tag!(MetaDate, "text:date");
284text_tag!(MetaTime, "text:time");
285// text:page-continuation
286text_tag!(MetaPageNumber, "text:page-number");
287// text:sender-firstname
288// text:sender-lastname
289// text:sender-initials
290// text:sender-title
291// text:sender-position
292// text:sender-email
293// text:sender-phone-private
294// text:sender-fax
295// text:sender-company
296// text:sender-phone-work
297// text:sender-street
298// text:sender-city
299// text:sender-postal-code
300// text:sender-country
301// text:sender-state-or-province
302// The <text:author-name> element represents the full name of the author of a document.
303text_tag!(MetaAuthorName, "text:author-name");
304// The <text:author-initials> element represents the initials of the author of a document.
305text_tag!(MetaAuthorInitials, "text:author-initials");
306// text:chapter
307text_tag!(MetaFileName, "text:file-name");
308// text:template-name
309text_tag!(MetaSheetName, "text:sheet-name");
310text_tag!(MetaInitialCreator, "text:initial-creator");
311text_tag!(MetaCreationDate, "text:creation-date");
312text_tag!(MetaCreationTime, "text:creation-time");
313text_tag!(MetaDescription, "text:description");
314// text:user-defined
315text_tag!(MetaPrintTime, "text:print-time");
316text_tag!(MetaPrintDate, "text:print-date");
317text_tag!(MetaPrintedBy, "text:printed-by");
318text_tag!(MetaTitle, "text:title");
319text_tag!(MetaSubject, "text:subject");
320text_tag!(MetaKeywords, "text:keywords");
321text_tag!(MetaEditingCycles, "text:editing-cycles");
322text_tag!(MetaEditingDuration, "text:editing-duration");
323text_tag!(MetaModificationTime, "text:modification-time");
324text_tag!(MetaModificationDate, "text:modification-date");
325text_tag!(MetaCreator, "text:creator");
326text_tag!(MetaPageCount, "text:page-count");
327// text:paragraph-count
328// text:word-count
329text_tag!(MetaCharacterCount, "text:character-count");
330// text:table-count
331// text:image-count
332// text:object-count
333// text:meta-field