public void StressTestInlineCSS() { initialHTML = "<html><head><title>TITLE</title><style>{0}</style></head>" + Environment.NewLine + "<body>" + Environment.NewLine + "<div>{1}</div>" + "</body></html>"; initialHTML = String.Format(initialHTML, GenerateStressTestStyle(), GenerateInitialElementsForStressTest()); initialXmlDoc = new XmlDocument(); initialXmlDoc.LoadXml(initialHTML); long startTicks = DateTime.Now.Ticks; CSSUtil.InlineCSS(ref initialXmlDoc); long stopTicks = DateTime.Now.Ticks; //inline operation duration, in miliseconds double inlineTimeMS = (1.0 * stopTicks - startTicks) / 10000; //inline operation should take less than 500 miliseconds Assert.IsTrue(inlineTimeMS < 500.00); }
public void TestInlineCSSNoStyleNodes() { initialXmlDoc = new XmlDocument(); expectedXmlDoc = new XmlDocument(); initialHTML = "<html><head><title>TITLE</title>" + "<style type=\"text/css\">" + Environment.NewLine + ".oneClass {font-family:sans-serif;font-size:90%;}" + "#oneId {color:red;}" + Environment.NewLine + "</style></head><body><h1>HEADER 1</h1>" + "<p class=\"oneClass\">Text 1</p>" + "<p><span id=\"oneId\">Text 2</span></p>" + "<p>Text 3 <span class=\"oneClass\" id=\"oneId\">Text 4</span> Text 5</p>" + "</body></html>"; expectedHTML = "<html><head><title>TITLE</title>" + "</head><body><h1>HEADER 1</h1>" + "<p style=\"font-family:sans-serif;font-size:90%;\">Text 1</p>" + "<p><span id=\"oneId\" style=\"color:red;\">Text 2</span></p>" + "<p>Text 3 <span id=\"oneId\" style=\"font-family:sans-serif;font-size:90%;color:red;\">Text 4</span> Text 5</p>" + "</body></html>"; initialXmlDoc.LoadXml(initialHTML); expectedXmlDoc.LoadXml(expectedHTML); CSSUtil.InlineCSS(ref initialXmlDoc); Assert.IsTrue(XmlDocComparator.AreIdentical(initialXmlDoc, expectedXmlDoc)); }
public void TestInlineCSSMoreRules() { initialXmlDoc = new XmlDocument(); expectedXmlDoc = new XmlDocument(); initialHTML = "<html><head><title>TITLE</title>" + "<style>" + ".aClass {font-family:sans-serif;}" + "p {font-size:100%;}" + ".aClass {color:#2020FF;}" + "p, .aClass {padding:3px;}" + "</style>" + "</head>" + "<body>" + "<p class=\"aClass\">Some text</p>" + "</body></html>"; expectedHTML = "<html><head><title>TITLE</title>" + "<style>" + "p {font-size:100%;}" + "p, .aClass {padding:3px;}" + "</style>" + "</head>" + "<body>" + "<p style=\"font-family:sans-serif;color:#2020FF;padding:3px;\">Some text</p>" + "</body></html>"; initialXmlDoc.LoadXml(initialHTML); expectedXmlDoc.LoadXml(expectedHTML); CSSUtil.InlineCSS(ref initialXmlDoc); Assert.IsTrue(XmlDocComparator.AreIdentical(initialXmlDoc, expectedXmlDoc)); }
void ProcCSS() { foreach (TextItem item in css) { CSSUtil.EditInSegment(ref item.data, ".ae_center{text-indent:0!important;text-align:center!important;}", ToString()); Log.log("[Info ]Added style to " + item.fullName); } }
void ProcCSS() { foreach (TextItem item in css) { CSSUtil.EditInSegment(ref item.data, ".ae_draw_out{text-indent:1.5em;}", ToString()); Log.log("[Info ]Added style to " + item.fullName); } }
public void Filter(ref XmlDocument xmlDoc) { XmlNode styleNode = GetStyleNode(ref xmlDoc); string cssContent = ExtractCSSFromStyleSheetExtensions(); styleNode.InnerText = cssContent; CSSUtil.InlineCSS(ref xmlDoc); }
public void TestGroupCSSSelectors() { Hashtable initialCSSClasses = new Hashtable(); Hashtable optimizedCSSClasses = new Hashtable(); //same initial CSS properties string props1 = "font-family:sans-serif;font-size:100%;color:red;"; string props2 = "color:red;font-size:100%;font-family:sans-serif;"; //the expected properties (ordered alphabetically) string expectedProp = "color:red;font-family:sans-serif;font-size:100%"; //initial CSS selectors string[] classes1 = { ".xoffice0", ".xoffice1", ".xoffice2", "textarea" }; string[] classes2 = { ".xoffice3", ".xoffice4", ".myCssClass", "#one", "p#two" }; for (int i = 0; i < classes1.Length; i++) { initialCSSClasses.Add(classes1[i], props1); } for (int i = 0; i < classes2.Length; i++) { initialCSSClasses.Add(classes2[i], props2); } optimizedCSSClasses = CSSUtil.GroupCSSSelectors(initialCSSClasses); ICollection optimizedKeys = optimizedCSSClasses.Keys; //all the selectors should be grouped Assert.IsTrue(optimizedKeys.Count == 1); foreach (string key in optimizedKeys) { string val = optimizedCSSClasses[key].ToString(); //in the new key there must be all initial CSS selectors foreach (string cssClass in classes1) { Assert.IsTrue(key.IndexOf(cssClass) >= 0); } foreach (string cssClass in classes2) { Assert.IsTrue(key.IndexOf(cssClass) >= 0); } //expected properties are the same, but ordered alphabetically Assert.IsTrue(val.IndexOf(expectedProp) >= 0); } }
public ProcCSS(TextItem css, FootnoteAdaptOption option) { switch (option) { case FootnoteAdaptOption.Main: { string c = "@media amzn-kf8{\naside{display:none;}\n.ae_note_inside{page-break-after:always;}\n}\n.ae_note_inside{text-indent:0;}"; CSSUtil.EditInSegment(ref css.data, c, "AeroEpubProcesser.FootnoteAdapter"); } break; case FootnoteAdaptOption.Main_Duokan: { string c = "@media amzn-kf8{\naside{display:none;}\n.duokan-footnote-item{page-break-after:always;}\n}"; CSSUtil.EditInSegment(ref css.data, c, "AeroEpubProcesser.FootnoteAdapter"); } break; } Log.log("[Info ]Added style to " + css.fullName); }
public void TestInlineCSSOneStyleNode() { initialXmlDoc = new XmlDocument(); expectedXmlDoc = new XmlDocument(); initialHTML = "<html><head><title>TITLE</title>" + "<style>" + "p,div, span {font-family:sans-serif;}" + ".normal {font-family:sans-serif;}" + "</style>" + "<style>" + ".code {font-family:monospace;}" + "#errmsg {color:red;}" + "</style>" + "</head>" + "<body>" + "<p class=\"normal\">Normal text</p>" + "<p class=\"code\">return 0;</p>" + "<p><span class=\"code\" id=\"errmsg\">Error message</span></p>" + "</body></html>"; expectedHTML = "<html><head><title>TITLE</title>" + "<style>" + "p,div, span {font-family:sans-serif;}" + "</style>" + "</head>" + "<body>" + "<p style=\"font-family:sans-serif;\">Normal text</p>" + "<p style=\"font-family:monospace;\">return 0;</p>" + "<p><span id=\"errmsg\" style=\"font-family:monospace;color:red;\">Error message</span></p>" + "</body></html>"; initialXmlDoc.LoadXml(initialHTML); expectedXmlDoc.LoadXml(expectedHTML); CSSUtil.InlineCSS(ref initialXmlDoc); Assert.IsTrue(XmlDocComparator.AreIdentical(initialXmlDoc, expectedXmlDoc)); }
/// <summary> /// Extracts the inline styles, optimizes CSS and adds CSS classes in the head section for current page /// </summary> /// <param name="xmlDoc">A reference to a XmlDocument instance.</param> public void Filter(ref System.Xml.XmlDocument xmlDoc) { XmlNode body = xmlDoc.GetElementsByTagName("body")[0]; XmlNode head = xmlDoc.GetElementsByTagName("head")[0]; if (head == null) { head = xmlDoc.CreateNode(XmlNodeType.Element, "head", xmlDoc.NamespaceURI); body.ParentNode.InsertBefore(head, body); } //step1: inline CSS for existing CSS classes and ids, for better manipulation at step2 and step3 CSSUtil.InlineCSS(ref xmlDoc); //step2: convert all inlined style to CSS classes //(including, but not limited to, those generated at step1) body = CSSUtil.ConvertInlineStylesToCssClasses(body, ref xmlDoc, ref counter, ref cssClasses); //step3: optimize CSS by grouping selectors with the same properties cssClasses = CSSUtil.GroupCSSSelectors(cssClasses); InsertCssClassesInHeader(ref head, ref xmlDoc); }
public void TestConvertInlineStylesToCssClasses() { initialXmlDoc = new XmlDocument(); expectedXmlDoc = new XmlDocument(); initialHTML = "<html><head><title>TITLE</title></head>" + "<body>" + "<div style=\"border:1px red solid;padding:3px;margin:3px;\">" + "<p style=\"font-family:sans-serif;\">Text 1</p>" + "<p style=\"font-family:sans-serif;\">Text 2</p>" + "<p style=\"font-family:sans-serif;\">" + "Text 3" + "<span style=\"color:orange;\">Text 4</span>" + "<span style=\"color:black;\">Text 5</span>" + "</p>" + "</div>" + "</body></html>"; initialXmlDoc.LoadXml(initialHTML); expectedHTML = "<html><head><title>TITLE</title></head>" + "<body>" + "<div class=\"xoffice0\">" + "<p class=\"xoffice1\">Text 1</p>" + "<p class=\"xoffice2\">Text 2</p>" + "<p class=\"xoffice3\">" + "Text 3" + "<span class=\"xoffice4\">Text 4</span>" + "<span class=\"xoffice5\">Text 5</span>" + "</p>" + "</div>" + "</body></html>"; expectedXmlDoc.LoadXml(expectedHTML); int counter = 0; Hashtable cssClasses = new Hashtable(); XmlNode node = initialXmlDoc.GetElementsByTagName("div")[0]; CSSUtil.ConvertInlineStylesToCssClasses(node, ref initialXmlDoc, ref counter, ref cssClasses); string[] properties = { "border:1px red solid;padding:3px;margin:3px;", "font-family:sans-serif;", "color:orange;", "color:black;" }; //after conversion we should get the expected document Assert.IsTrue(XmlDocComparator.AreIdentical(expectedXmlDoc, initialXmlDoc)); //6 key/value pairs in cssClasses hashtable Assert.IsTrue(cssClasses.Count == 6); //6 CSS classes from .xoffice0 to .xoffice5 for (int i = 0; i < 6; i++) { Assert.IsTrue(cssClasses.ContainsKey(".xoffice" + i)); } //all the properties extracted from inline styles should be found in the cssClasses hashtable foreach (string cssProp in properties) { Assert.IsTrue(cssClasses.ContainsValue(cssProp)); } }
void ProcCSS(TextItem item) { CSSUtil.EditInSegment(ref item.data, "p{line-height:1.5;margin-top:0;margin-bottom:0;}", ToString()); Log.log("[Info ]Added style to " + item.fullName); }