umya_spreadsheet/helper/
html.rs

1use crate::structs::Color;
2use crate::structs::Font;
3use crate::structs::RichText;
4use crate::structs::TextElement;
5use crate::structs::UnderlineValues;
6use crate::structs::VerticalAlignmentRunValues;
7use chrono::format;
8use html_parser::{Dom, Element, Node};
9use std::collections::HashMap;
10use thin_vec::ThinVec;
11
12/// Generate rich text from html.
13/// # Arguments
14/// * `html` - HTML String.
15/// # Return value
16/// * `Result<RichText, html_parser::Error>`
17/// # Examples
18/// ```
19/// let html = r##"<font color="red">test</font><br><font class="test" color="#48D1CC">TE<b>S</b>T<br/>TEST</font>"##;
20/// let richtext = umya_spreadsheet::helper::html::html_to_richtext(html).unwrap();
21///
22/// let mut book = umya_spreadsheet::new_file();
23/// let mut sheet = book.get_sheet_by_name_mut("Sheet1").unwrap();
24/// sheet.get_cell_mut("A1").set_rich_text(richtext);
25/// // Enable line breaks.
26/// sheet
27///     .get_cell_mut("A1")
28///     .get_style_mut()
29///     .get_alignment_mut()
30///     .set_wrap_text(true);
31/// ```
32#[inline]
33pub fn html_to_richtext(html: &str) -> Result<RichText, html_parser::Error> {
34    html_to_richtext_custom(html, &DataAnalysis::default())
35}
36
37/// Use here for custom html parsing.
38/// # Arguments
39/// * `html` - HTML String.
40/// * `method` - struct for analysis.
41/// # Return value
42/// * `Result<RichText, html_parser::Error>`
43#[inline]
44pub fn html_to_richtext_custom(
45    html: &str,
46    method: &dyn AnalysisMethod,
47) -> Result<RichText, html_parser::Error> {
48    let dom = Dom::parse(html)?;
49    let data = read_node(&dom.children, &Vec::new());
50    let result = make_rich_text(&data, method);
51    Ok(result)
52}
53
54fn read_node(node_list: &Vec<Node>, parent_element: &[HfdElement]) -> ThinVec<HtmlFlatData> {
55    let mut result: ThinVec<HtmlFlatData> = ThinVec::new();
56
57    if node_list.is_empty() {
58        return result;
59    }
60
61    let mut data = HtmlFlatData::default();
62    data.element.extend_from_slice(parent_element);
63
64    for node in node_list {
65        match node {
66            Node::Text(text) => {
67                data.text = format!("{}{}", data.text, text);
68            }
69            Node::Element(element) => {
70                if &element.name == "br" {
71                    data.text = format!("{}{}", data.text, "\n");
72                    continue;
73                }
74                if &data.text != "" {
75                    result.push(data);
76                    data = HtmlFlatData::default();
77                    data.element.extend_from_slice(parent_element);
78                }
79
80                let mut elm: HfdElement = HfdElement::default();
81                elm.name = element.name.to_string();
82
83                elm.attributes = element
84                    .attributes
85                    .iter()
86                    .map(|(name, value)| {
87                        (
88                            name.clone(),
89                            value.as_ref().map(|v| v.to_string()).unwrap_or_default(),
90                        )
91                    })
92                    .collect();
93
94                elm.classes = element.classes.clone().into();
95                data.element.push(elm);
96
97                let mut children = read_node(&element.children, &data.element);
98                result.append(&mut children);
99
100                data = HtmlFlatData::default();
101                data.element.extend_from_slice(parent_element);
102            }
103            _ => {}
104        }
105    }
106    if &data.text != "" {
107        result.push(data);
108    }
109    result
110}
111
112fn make_rich_text(html_flat_data_list: &[HtmlFlatData], method: &dyn AnalysisMethod) -> RichText {
113    let mut result = RichText::default();
114
115    for html_flat_data in html_flat_data_list {
116        let mut font_name: Option<&str> = method.font_name(html_flat_data);
117        let mut size: Option<f64> = method.size(html_flat_data);
118        let mut color: Option<String> = method.color(html_flat_data);
119        let mut is_bold: bool = method.is_bold(html_flat_data);
120        let mut is_italic: bool = method.is_italic(html_flat_data);
121        let mut is_underline: bool = method.is_underline(html_flat_data);
122        let mut is_superscript: bool = method.is_superscript(html_flat_data);
123        let mut is_subscript: bool = method.is_subscript(html_flat_data);
124        let mut is_strikethrough: bool = method.is_strikethrough(html_flat_data);
125
126        let mut text_element = TextElement::default();
127        let mut font = Font::default();
128
129        if let Some(v) = font_name {
130            font.set_name(v);
131        }
132
133        if let Some(v) = size {
134            font.set_size(v);
135        }
136
137        if let Some(v) = color {
138            let argb = v;
139            let mut clr = Color::default();
140            clr.set_argb(argb);
141            font.set_color(clr);
142        }
143
144        if is_bold {
145            font.set_bold(is_bold);
146        }
147        if is_italic {
148            font.set_italic(is_italic);
149        }
150        if is_underline {
151            font.get_font_underline_mut()
152                .set_val(UnderlineValues::Single);
153        }
154        if is_superscript {
155            font.get_vertical_text_alignment_mut()
156                .set_val(VerticalAlignmentRunValues::Superscript);
157        }
158        if is_subscript {
159            font.get_vertical_text_alignment_mut()
160                .set_val(VerticalAlignmentRunValues::Subscript);
161        }
162        if is_strikethrough {
163            font.set_strikethrough(is_strikethrough);
164        }
165
166        text_element.set_text(&html_flat_data.text);
167        text_element.set_run_properties(font);
168        result.add_rich_text_elements(text_element);
169    }
170    result
171}
172
173#[derive(Clone, Default, Debug)]
174pub struct HtmlFlatData {
175    text: String,
176    element: ThinVec<HfdElement>,
177}
178
179#[derive(Clone, Default, Debug)]
180pub struct HfdElement {
181    name: String,
182    attributes: HashMap<String, String>,
183    classes: ThinVec<String>,
184}
185impl HfdElement {
186    #[inline]
187    pub fn has_name(&self, name: &str) -> bool {
188        self.name == name
189    }
190
191    #[inline]
192    pub fn get_by_name_and_attribute(&self, name: &str, attribute: &str) -> Option<&str> {
193        self.attributes
194            .get(attribute)
195            .and_then(|v| (self.name == name).then(|| v))
196            .map(|x| x.as_str())
197    }
198
199    #[inline]
200    pub fn contains_class(&self, class: &str) -> bool {
201        self.classes.contains(&class.to_string())
202    }
203}
204
205pub trait AnalysisMethod {
206    fn is_tag(&self, html_flat_data: &HtmlFlatData, tag: &str) -> bool;
207    fn font_name<'a>(&'a self, html_flat_data: &'a HtmlFlatData) -> Option<&'a str>;
208    fn size(&self, html_flat_data: &HtmlFlatData) -> Option<f64>;
209    fn color(&self, html_flat_data: &HtmlFlatData) -> Option<String>;
210    fn is_bold(&self, html_flat_data: &HtmlFlatData) -> bool;
211    fn is_italic(&self, html_flat_data: &HtmlFlatData) -> bool;
212    fn is_underline(&self, html_flat_data: &HtmlFlatData) -> bool;
213    fn is_superscript(&self, html_flat_data: &HtmlFlatData) -> bool;
214    fn is_subscript(&self, html_flat_data: &HtmlFlatData) -> bool;
215    fn is_strikethrough(&self, html_flat_data: &HtmlFlatData) -> bool;
216}
217
218#[derive(Clone, Default, Debug)]
219struct DataAnalysis {}
220impl AnalysisMethod for DataAnalysis {
221    #[inline]
222    fn font_name<'a>(&'a self, html_flat_data: &'a HtmlFlatData) -> Option<&str> {
223        html_flat_data
224            .element
225            .iter()
226            .find_map(|element| element.get_by_name_and_attribute("font", "face"))
227    }
228
229    #[inline]
230    fn size(&self, html_flat_data: &HtmlFlatData) -> Option<f64> {
231        html_flat_data.element.iter().find_map(|element| {
232            element
233                .get_by_name_and_attribute("font", "size")
234                .and_then(|v| v.parse::<f64>().ok())
235        })
236    }
237
238    fn color(&self, html_flat_data: &HtmlFlatData) -> Option<String> {
239        let mut result: Option<String> = None;
240        html_flat_data
241            .element
242            .iter()
243            .flat_map(|element| element.get_by_name_and_attribute("font", "color"))
244            .find_map(|v| {
245                let color = v.trim_start_matches('#').to_uppercase();
246                COLOR_MAP
247                    .iter()
248                    .find_map(|(key, value)| {
249                        (*key.to_uppercase() == color).then(|| value.to_uppercase())
250                    })
251                    .or_else(|| Some(color))
252            })
253    }
254
255    #[inline]
256    fn is_tag(&self, html_flat_data: &HtmlFlatData, tag: &str) -> bool {
257        html_flat_data
258            .element
259            .iter()
260            .any(|element| element.has_name(tag))
261    }
262
263    #[inline]
264    fn is_bold(&self, html_flat_data: &HtmlFlatData) -> bool {
265        self.is_tag(html_flat_data, "b") || self.is_tag(html_flat_data, "strong")
266    }
267
268    #[inline]
269    fn is_italic(&self, html_flat_data: &HtmlFlatData) -> bool {
270        self.is_tag(html_flat_data, "i") || self.is_tag(html_flat_data, "em")
271    }
272
273    #[inline]
274    fn is_underline(&self, html_flat_data: &HtmlFlatData) -> bool {
275        self.is_tag(html_flat_data, "u") || self.is_tag(html_flat_data, "ins")
276    }
277
278    #[inline]
279    fn is_superscript(&self, html_flat_data: &HtmlFlatData) -> bool {
280        self.is_tag(html_flat_data, "sup")
281    }
282
283    #[inline]
284    fn is_subscript(&self, html_flat_data: &HtmlFlatData) -> bool {
285        self.is_tag(html_flat_data, "sub")
286    }
287
288    #[inline]
289    fn is_strikethrough(&self, html_flat_data: &HtmlFlatData) -> bool {
290        self.is_tag(html_flat_data, "del")
291    }
292}
293
294const COLOR_MAP: &[(&str, &str)] = &[
295    ("aliceblue", "f0f8ff"),
296    ("antiquewhite", "faebd7"),
297    ("antiquewhite1", "ffefdb"),
298    ("antiquewhite2", "eedfcc"),
299    ("antiquewhite3", "cdc0b0"),
300    ("antiquewhite4", "8b8378"),
301    ("aqua", "00ffff"),
302    ("aquamarine1", "7fffd4"),
303    ("aquamarine2", "76eec6"),
304    ("aquamarine4", "458b74"),
305    ("azure1", "f0ffff"),
306    ("azure2", "e0eeee"),
307    ("azure3", "c1cdcd"),
308    ("azure4", "838b8b"),
309    ("beige", "f5f5dc"),
310    ("bisque1", "ffe4c4"),
311    ("bisque2", "eed5b7"),
312    ("bisque3", "cdb79e"),
313    ("bisque4", "8b7d6b"),
314    ("black", "000000"),
315    ("blanchedalmond", "ffebcd"),
316    ("blue", "0000ff"),
317    ("blue1", "0000ff"),
318    ("blue2", "0000ee"),
319    ("blue4", "00008b"),
320    ("blueviolet", "8a2be2"),
321    ("brown", "a52a2a"),
322    ("brown1", "ff4040"),
323    ("brown2", "ee3b3b"),
324    ("brown3", "cd3333"),
325    ("brown4", "8b2323"),
326    ("burlywood", "deb887"),
327    ("burlywood1", "ffd39b"),
328    ("burlywood2", "eec591"),
329    ("burlywood3", "cdaa7d"),
330    ("burlywood4", "8b7355"),
331    ("cadetblue", "5f9ea0"),
332    ("cadetblue1", "98f5ff"),
333    ("cadetblue2", "8ee5ee"),
334    ("cadetblue3", "7ac5cd"),
335    ("cadetblue4", "53868b"),
336    ("chartreuse1", "7fff00"),
337    ("chartreuse2", "76ee00"),
338    ("chartreuse3", "66cd00"),
339    ("chartreuse4", "458b00"),
340    ("chocolate", "d2691e"),
341    ("chocolate1", "ff7f24"),
342    ("chocolate2", "ee7621"),
343    ("chocolate3", "cd661d"),
344    ("coral", "ff7f50"),
345    ("coral1", "ff7256"),
346    ("coral2", "ee6a50"),
347    ("coral3", "cd5b45"),
348    ("coral4", "8b3e2f"),
349    ("cornflowerblue", "6495ed"),
350    ("cornsilk1", "fff8dc"),
351    ("cornsilk2", "eee8cd"),
352    ("cornsilk3", "cdc8b1"),
353    ("cornsilk4", "8b8878"),
354    ("cyan1", "00ffff"),
355    ("cyan2", "00eeee"),
356    ("cyan3", "00cdcd"),
357    ("cyan4", "008b8b"),
358    ("darkgoldenrod", "b8860b"),
359    ("darkgoldenrod1", "ffb90f"),
360    ("darkgoldenrod2", "eead0e"),
361    ("darkgoldenrod3", "cd950c"),
362    ("darkgoldenrod4", "8b6508"),
363    ("darkgreen", "006400"),
364    ("darkkhaki", "bdb76b"),
365    ("darkolivegreen", "556b2f"),
366    ("darkolivegreen1", "caff70"),
367    ("darkolivegreen2", "bcee68"),
368    ("darkolivegreen3", "a2cd5a"),
369    ("darkolivegreen4", "6e8b3d"),
370    ("darkorange", "ff8c00"),
371    ("darkorange1", "ff7f00"),
372    ("darkorange2", "ee7600"),
373    ("darkorange3", "cd6600"),
374    ("darkorange4", "8b4500"),
375    ("darkorchid", "9932cc"),
376    ("darkorchid1", "bf3eff"),
377    ("darkorchid2", "b23aee"),
378    ("darkorchid3", "9a32cd"),
379    ("darkorchid4", "68228b"),
380    ("darksalmon", "e9967a"),
381    ("darkseagreen", "8fbc8f"),
382    ("darkseagreen1", "c1ffc1"),
383    ("darkseagreen2", "b4eeb4"),
384    ("darkseagreen3", "9bcd9b"),
385    ("darkseagreen4", "698b69"),
386    ("darkslateblue", "483d8b"),
387    ("darkslategray", "2f4f4f"),
388    ("darkslategray1", "97ffff"),
389    ("darkslategray2", "8deeee"),
390    ("darkslategray3", "79cdcd"),
391    ("darkslategray4", "528b8b"),
392    ("darkturquoise", "00ced1"),
393    ("darkviolet", "9400d3"),
394    ("deeppink1", "ff1493"),
395    ("deeppink2", "ee1289"),
396    ("deeppink3", "cd1076"),
397    ("deeppink4", "8b0a50"),
398    ("deepskyblue1", "00bfff"),
399    ("deepskyblue2", "00b2ee"),
400    ("deepskyblue3", "009acd"),
401    ("deepskyblue4", "00688b"),
402    ("dimgray", "696969"),
403    ("dodgerblue1", "1e90ff"),
404    ("dodgerblue2", "1c86ee"),
405    ("dodgerblue3", "1874cd"),
406    ("dodgerblue4", "104e8b"),
407    ("firebrick", "b22222"),
408    ("firebrick1", "ff3030"),
409    ("firebrick2", "ee2c2c"),
410    ("firebrick3", "cd2626"),
411    ("firebrick4", "8b1a1a"),
412    ("floralwhite", "fffaf0"),
413    ("forestgreen", "228b22"),
414    ("fuchsia", "ff00ff"),
415    ("gainsboro", "dcdcdc"),
416    ("ghostwhite", "f8f8ff"),
417    ("gold1", "ffd700"),
418    ("gold2", "eec900"),
419    ("gold3", "cdad00"),
420    ("gold4", "8b7500"),
421    ("goldenrod", "daa520"),
422    ("goldenrod1", "ffc125"),
423    ("goldenrod2", "eeb422"),
424    ("goldenrod3", "cd9b1d"),
425    ("goldenrod4", "8b6914"),
426    ("gray", "bebebe"),
427    ("gray1", "030303"),
428    ("gray10", "1a1a1a"),
429    ("gray11", "1c1c1c"),
430    ("gray12", "1f1f1f"),
431    ("gray13", "212121"),
432    ("gray14", "242424"),
433    ("gray15", "262626"),
434    ("gray16", "292929"),
435    ("gray17", "2b2b2b"),
436    ("gray18", "2e2e2e"),
437    ("gray19", "303030"),
438    ("gray2", "050505"),
439    ("gray20", "333333"),
440    ("gray21", "363636"),
441    ("gray22", "383838"),
442    ("gray23", "3b3b3b"),
443    ("gray24", "3d3d3d"),
444    ("gray25", "404040"),
445    ("gray26", "424242"),
446    ("gray27", "454545"),
447    ("gray28", "474747"),
448    ("gray29", "4a4a4a"),
449    ("gray3", "080808"),
450    ("gray30", "4d4d4d"),
451    ("gray31", "4f4f4f"),
452    ("gray32", "525252"),
453    ("gray33", "545454"),
454    ("gray34", "575757"),
455    ("gray35", "595959"),
456    ("gray36", "5c5c5c"),
457    ("gray37", "5e5e5e"),
458    ("gray38", "616161"),
459    ("gray39", "636363"),
460    ("gray4", "0a0a0a"),
461    ("gray40", "666666"),
462    ("gray41", "696969"),
463    ("gray42", "6b6b6b"),
464    ("gray43", "6e6e6e"),
465    ("gray44", "707070"),
466    ("gray45", "737373"),
467    ("gray46", "757575"),
468    ("gray47", "787878"),
469    ("gray48", "7a7a7a"),
470    ("gray49", "7d7d7d"),
471    ("gray5", "0d0d0d"),
472    ("gray50", "7f7f7f"),
473    ("gray51", "828282"),
474    ("gray52", "858585"),
475    ("gray53", "878787"),
476    ("gray54", "8a8a8a"),
477    ("gray55", "8c8c8c"),
478    ("gray56", "8f8f8f"),
479    ("gray57", "919191"),
480    ("gray58", "949494"),
481    ("gray59", "969696"),
482    ("gray6", "0f0f0f"),
483    ("gray60", "999999"),
484    ("gray61", "9c9c9c"),
485    ("gray62", "9e9e9e"),
486    ("gray63", "a1a1a1"),
487    ("gray64", "a3a3a3"),
488    ("gray65", "a6a6a6"),
489    ("gray66", "a8a8a8"),
490    ("gray67", "ababab"),
491    ("gray68", "adadad"),
492    ("gray69", "b0b0b0"),
493    ("gray7", "121212"),
494    ("gray70", "b3b3b3"),
495    ("gray71", "b5b5b5"),
496    ("gray72", "b8b8b8"),
497    ("gray73", "bababa"),
498    ("gray74", "bdbdbd"),
499    ("gray75", "bfbfbf"),
500    ("gray76", "c2c2c2"),
501    ("gray77", "c4c4c4"),
502    ("gray78", "c7c7c7"),
503    ("gray79", "c9c9c9"),
504    ("gray8", "141414"),
505    ("gray80", "cccccc"),
506    ("gray81", "cfcfcf"),
507    ("gray82", "d1d1d1"),
508    ("gray83", "d4d4d4"),
509    ("gray84", "d6d6d6"),
510    ("gray85", "d9d9d9"),
511    ("gray86", "dbdbdb"),
512    ("gray87", "dedede"),
513    ("gray88", "e0e0e0"),
514    ("gray89", "e3e3e3"),
515    ("gray9", "171717"),
516    ("gray90", "e5e5e5"),
517    ("gray91", "e8e8e8"),
518    ("gray92", "ebebeb"),
519    ("gray93", "ededed"),
520    ("gray94", "f0f0f0"),
521    ("gray95", "f2f2f2"),
522    ("gray97", "f7f7f7"),
523    ("gray98", "fafafa"),
524    ("gray99", "fcfcfc"),
525    ("green", "00ff00"),
526    ("green1", "00ff00"),
527    ("green2", "00ee00"),
528    ("green3", "00cd00"),
529    ("green4", "008b00"),
530    ("greenyellow", "adff2f"),
531    ("honeydew1", "f0fff0"),
532    ("honeydew2", "e0eee0"),
533    ("honeydew3", "c1cdc1"),
534    ("honeydew4", "838b83"),
535    ("hotpink", "ff69b4"),
536    ("hotpink1", "ff6eb4"),
537    ("hotpink2", "ee6aa7"),
538    ("hotpink3", "cd6090"),
539    ("hotpink4", "8b3a62"),
540    ("indianred", "cd5c5c"),
541    ("indianred1", "ff6a6a"),
542    ("indianred2", "ee6363"),
543    ("indianred3", "cd5555"),
544    ("indianred4", "8b3a3a"),
545    ("ivory1", "fffff0"),
546    ("ivory2", "eeeee0"),
547    ("ivory3", "cdcdc1"),
548    ("ivory4", "8b8b83"),
549    ("khaki", "f0e68c"),
550    ("khaki1", "fff68f"),
551    ("khaki2", "eee685"),
552    ("khaki3", "cdc673"),
553    ("khaki4", "8b864e"),
554    ("lavender", "e6e6fa"),
555    ("lavenderblush1", "fff0f5"),
556    ("lavenderblush2", "eee0e5"),
557    ("lavenderblush3", "cdc1c5"),
558    ("lavenderblush4", "8b8386"),
559    ("lawngreen", "7cfc00"),
560    ("lemonchiffon1", "fffacd"),
561    ("lemonchiffon2", "eee9bf"),
562    ("lemonchiffon3", "cdc9a5"),
563    ("lemonchiffon4", "8b8970"),
564    ("light", "eedd82"),
565    ("lightblue", "add8e6"),
566    ("lightblue1", "bfefff"),
567    ("lightblue2", "b2dfee"),
568    ("lightblue3", "9ac0cd"),
569    ("lightblue4", "68838b"),
570    ("lightcoral", "f08080"),
571    ("lightcyan1", "e0ffff"),
572    ("lightcyan2", "d1eeee"),
573    ("lightcyan3", "b4cdcd"),
574    ("lightcyan4", "7a8b8b"),
575    ("lightgoldenrod1", "ffec8b"),
576    ("lightgoldenrod2", "eedc82"),
577    ("lightgoldenrod3", "cdbe70"),
578    ("lightgoldenrod4", "8b814c"),
579    ("lightgoldenrodyellow", "fafad2"),
580    ("lightgray", "d3d3d3"),
581    ("lightpink", "ffb6c1"),
582    ("lightpink1", "ffaeb9"),
583    ("lightpink2", "eea2ad"),
584    ("lightpink3", "cd8c95"),
585    ("lightpink4", "8b5f65"),
586    ("lightsalmon1", "ffa07a"),
587    ("lightsalmon2", "ee9572"),
588    ("lightsalmon3", "cd8162"),
589    ("lightsalmon4", "8b5742"),
590    ("lightseagreen", "20b2aa"),
591    ("lightskyblue", "87cefa"),
592    ("lightskyblue1", "b0e2ff"),
593    ("lightskyblue2", "a4d3ee"),
594    ("lightskyblue3", "8db6cd"),
595    ("lightskyblue4", "607b8b"),
596    ("lightslateblue", "8470ff"),
597    ("lightslategray", "778899"),
598    ("lightsteelblue", "b0c4de"),
599    ("lightsteelblue1", "cae1ff"),
600    ("lightsteelblue2", "bcd2ee"),
601    ("lightsteelblue3", "a2b5cd"),
602    ("lightsteelblue4", "6e7b8b"),
603    ("lightyellow1", "ffffe0"),
604    ("lightyellow2", "eeeed1"),
605    ("lightyellow3", "cdcdb4"),
606    ("lightyellow4", "8b8b7a"),
607    ("lime", "00ff00"),
608    ("limegreen", "32cd32"),
609    ("linen", "faf0e6"),
610    ("magenta", "ff00ff"),
611    ("magenta2", "ee00ee"),
612    ("magenta3", "cd00cd"),
613    ("magenta4", "8b008b"),
614    ("maroon", "b03060"),
615    ("maroon1", "ff34b3"),
616    ("maroon2", "ee30a7"),
617    ("maroon3", "cd2990"),
618    ("maroon4", "8b1c62"),
619    ("medium", "66cdaa"),
620    ("mediumaquamarine", "66cdaa"),
621    ("mediumblue", "0000cd"),
622    ("mediumorchid", "ba55d3"),
623    ("mediumorchid1", "e066ff"),
624    ("mediumorchid2", "d15fee"),
625    ("mediumorchid3", "b452cd"),
626    ("mediumorchid4", "7a378b"),
627    ("mediumpurple", "9370db"),
628    ("mediumpurple1", "ab82ff"),
629    ("mediumpurple2", "9f79ee"),
630    ("mediumpurple3", "8968cd"),
631    ("mediumpurple4", "5d478b"),
632    ("mediumseagreen", "3cb371"),
633    ("mediumslateblue", "7b68ee"),
634    ("mediumspringgreen", "00fa9a"),
635    ("mediumturquoise", "48d1cc"),
636    ("mediumvioletred", "c71585"),
637    ("midnightblue", "191970"),
638    ("mintcream", "f5fffa"),
639    ("mistyrose1", "ffe4e1"),
640    ("mistyrose2", "eed5d2"),
641    ("mistyrose3", "cdb7b5"),
642    ("mistyrose4", "8b7d7b"),
643    ("moccasin", "ffe4b5"),
644    ("navajowhite1", "ffdead"),
645    ("navajowhite2", "eecfa1"),
646    ("navajowhite3", "cdb38b"),
647    ("navajowhite4", "8b795e"),
648    ("navy", "000080"),
649    ("navyblue", "000080"),
650    ("oldlace", "fdf5e6"),
651    ("olive", "808000"),
652    ("olivedrab", "6b8e23"),
653    ("olivedrab1", "c0ff3e"),
654    ("olivedrab2", "b3ee3a"),
655    ("olivedrab4", "698b22"),
656    ("orange", "ffa500"),
657    ("orange1", "ffa500"),
658    ("orange2", "ee9a00"),
659    ("orange3", "cd8500"),
660    ("orange4", "8b5a00"),
661    ("orangered1", "ff4500"),
662    ("orangered2", "ee4000"),
663    ("orangered3", "cd3700"),
664    ("orangered4", "8b2500"),
665    ("orchid", "da70d6"),
666    ("orchid1", "ff83fa"),
667    ("orchid2", "ee7ae9"),
668    ("orchid3", "cd69c9"),
669    ("orchid4", "8b4789"),
670    ("pale", "db7093"),
671    ("palegoldenrod", "eee8aa"),
672    ("palegreen", "98fb98"),
673    ("palegreen1", "9aff9a"),
674    ("palegreen2", "90ee90"),
675    ("palegreen3", "7ccd7c"),
676    ("palegreen4", "548b54"),
677    ("paleturquoise", "afeeee"),
678    ("paleturquoise1", "bbffff"),
679    ("paleturquoise2", "aeeeee"),
680    ("paleturquoise3", "96cdcd"),
681    ("paleturquoise4", "668b8b"),
682    ("palevioletred", "db7093"),
683    ("palevioletred1", "ff82ab"),
684    ("palevioletred2", "ee799f"),
685    ("palevioletred3", "cd6889"),
686    ("palevioletred4", "8b475d"),
687    ("papayawhip", "ffefd5"),
688    ("peachpuff1", "ffdab9"),
689    ("peachpuff2", "eecbad"),
690    ("peachpuff3", "cdaf95"),
691    ("peachpuff4", "8b7765"),
692    ("pink", "ffc0cb"),
693    ("pink1", "ffb5c5"),
694    ("pink2", "eea9b8"),
695    ("pink3", "cd919e"),
696    ("pink4", "8b636c"),
697    ("plum", "dda0dd"),
698    ("plum1", "ffbbff"),
699    ("plum2", "eeaeee"),
700    ("plum3", "cd96cd"),
701    ("plum4", "8b668b"),
702    ("powderblue", "b0e0e6"),
703    ("purple", "a020f0"),
704    ("rebeccapurple", "663399"),
705    ("purple1", "9b30ff"),
706    ("purple2", "912cee"),
707    ("purple3", "7d26cd"),
708    ("purple4", "551a8b"),
709    ("red", "ff0000"),
710    ("red1", "ff0000"),
711    ("red2", "ee0000"),
712    ("red3", "cd0000"),
713    ("red4", "8b0000"),
714    ("rosybrown", "bc8f8f"),
715    ("rosybrown1", "ffc1c1"),
716    ("rosybrown2", "eeb4b4"),
717    ("rosybrown3", "cd9b9b"),
718    ("rosybrown4", "8b6969"),
719    ("royalblue", "4169e1"),
720    ("royalblue1", "4876ff"),
721    ("royalblue2", "436eee"),
722    ("royalblue3", "3a5fcd"),
723    ("royalblue4", "27408b"),
724    ("saddlebrown", "8b4513"),
725    ("salmon", "fa8072"),
726    ("salmon1", "ff8c69"),
727    ("salmon2", "ee8262"),
728    ("salmon3", "cd7054"),
729    ("salmon4", "8b4c39"),
730    ("sandybrown", "f4a460"),
731    ("seagreen1", "54ff9f"),
732    ("seagreen2", "4eee94"),
733    ("seagreen3", "43cd80"),
734    ("seagreen4", "2e8b57"),
735    ("seashell1", "fff5ee"),
736    ("seashell2", "eee5de"),
737    ("seashell3", "cdc5bf"),
738    ("seashell4", "8b8682"),
739    ("sienna", "a0522d"),
740    ("sienna1", "ff8247"),
741    ("sienna2", "ee7942"),
742    ("sienna3", "cd6839"),
743    ("sienna4", "8b4726"),
744    ("silver", "c0c0c0"),
745    ("skyblue", "87ceeb"),
746    ("skyblue1", "87ceff"),
747    ("skyblue2", "7ec0ee"),
748    ("skyblue3", "6ca6cd"),
749    ("skyblue4", "4a708b"),
750    ("slateblue", "6a5acd"),
751    ("slateblue1", "836fff"),
752    ("slateblue2", "7a67ee"),
753    ("slateblue3", "6959cd"),
754    ("slateblue4", "473c8b"),
755    ("slategray", "708090"),
756    ("slategray1", "c6e2ff"),
757    ("slategray2", "b9d3ee"),
758    ("slategray3", "9fb6cd"),
759    ("slategray4", "6c7b8b"),
760    ("snow1", "fffafa"),
761    ("snow2", "eee9e9"),
762    ("snow3", "cdc9c9"),
763    ("snow4", "8b8989"),
764    ("springgreen1", "00ff7f"),
765    ("springgreen2", "00ee76"),
766    ("springgreen3", "00cd66"),
767    ("springgreen4", "008b45"),
768    ("steelblue", "4682b4"),
769    ("steelblue1", "63b8ff"),
770    ("steelblue2", "5cacee"),
771    ("steelblue3", "4f94cd"),
772    ("steelblue4", "36648b"),
773    ("tan", "d2b48c"),
774    ("tan1", "ffa54f"),
775    ("tan2", "ee9a49"),
776    ("tan3", "cd853f"),
777    ("tan4", "8b5a2b"),
778    ("teal", "008080"),
779    ("thistle", "d8bfd8"),
780    ("thistle1", "ffe1ff"),
781    ("thistle2", "eed2ee"),
782    ("thistle3", "cdb5cd"),
783    ("thistle4", "8b7b8b"),
784    ("tomato1", "ff6347"),
785    ("tomato2", "ee5c42"),
786    ("tomato3", "cd4f39"),
787    ("tomato4", "8b3626"),
788    ("turquoise", "40e0d0"),
789    ("turquoise1", "00f5ff"),
790    ("turquoise2", "00e5ee"),
791    ("turquoise3", "00c5cd"),
792    ("turquoise4", "00868b"),
793    ("violet", "ee82ee"),
794    ("violetred", "d02090"),
795    ("violetred1", "ff3e96"),
796    ("violetred2", "ee3a8c"),
797    ("violetred3", "cd3278"),
798    ("violetred4", "8b2252"),
799    ("wheat", "f5deb3"),
800    ("wheat1", "ffe7ba"),
801    ("wheat2", "eed8ae"),
802    ("wheat3", "cdba96"),
803    ("wheat4", "8b7e66"),
804    ("white", "ffffff"),
805    ("whitesmoke", "f5f5f5"),
806    ("yellow", "ffff00"),
807    ("yellow1", "ffff00"),
808    ("yellow2", "eeee00"),
809    ("yellow3", "cdcd00"),
810    ("yellow4", "8b8b00"),
811    ("yellowgreen", "9acd32"),
812];
813
814#[test]
815fn convert_test() {
816    let html = r#"<font color="red">test</font><br><font class="test" color="green">TE<b>S</b>T<br/>TEST</font>"#;
817    let result = html_to_richtext(html).unwrap();
818}