Index: xword/ContentFiltering/Html/CSSUtil.cs =================================================================== --- xword/ContentFiltering/Html/CSSUtil.cs (revision 22662) +++ xword/ContentFiltering/Html/CSSUtil.cs (working copy) @@ -87,6 +87,9 @@ XmlNodeList styleNodes = xmlDoc.GetElementsByTagName("style"); StringBuilder preservedCSS = new StringBuilder(); + //a list of unique CSS rules + List cssRules = new List(); + //extract CSS classes and ids Hashtable identifiedCSSClassesAndIDs = new Hashtable(); foreach (XmlNode styleNode in styleNodes) @@ -125,7 +128,12 @@ } else //since we can not handle that CSS, preserve it { - preservedCSS.Append(cssClass).Append("}").Append(Environment.NewLine); + string rule=cssClass+"}"; + if (!cssRules.Contains(rule)) + { + cssRules.Add(rule); + preservedCSS.Append(rule).Append(Environment.NewLine); + } } } Index: xword/ContentFiltering/Test/Html/CSSUtilTest.cs =================================================================== --- xword/ContentFiltering/Test/Html/CSSUtilTest.cs (revision 22662) +++ xword/ContentFiltering/Test/Html/CSSUtilTest.cs (working copy) @@ -45,11 +45,15 @@ } /// - /// Tests the InlineCSS method. + /// Tests the InlineCSS method. All the CSS classes and ids should be inlined. + /// The style node should be removed. Class attributes should be removed. /// [Test] - public void TestInlineCSS() + public void TestInlineCSSNoStyleNodes() { + initialXmlDoc = new XmlDocument(); + expectedXmlDoc = new XmlDocument(); + initialHTML = "TITLE" + "

HEADER 1

" - + "

Text 1

" + + "

HEADER 1

" + + "

Text 1

" + "

Text 2

" - + "

Text 3 Text 4 Text 5

" + + "

Text 3 Text 4 Text 5

" + ""; initialXmlDoc.LoadXml(initialHTML); @@ -82,6 +81,92 @@ } /// + /// Tests the InlineCSS method. Some CSS classes and ids should be inlined. + /// Onle one style node should remain with CSS that couldn't be inlined. + /// Class attributes should be removed for the nodes where CSS was inlined. + /// + [Test] + public void TestInlineCSSOneStyleNode() + { + initialXmlDoc = new XmlDocument(); + expectedXmlDoc = new XmlDocument(); + + initialHTML = "TITLE" + + "" + + "" + + "" + + "" + + "

Normal text

" + + "

return 0;

" + + "

Error message

" + + ""; + + expectedHTML = "TITLE" + + "" + + "" + + "" + + "

Normal text

" + + "

return 0;

" + + "

Error message

" + + ""; + + initialXmlDoc.LoadXml(initialHTML); + expectedXmlDoc.LoadXml(expectedHTML); + + CSSUtil.InlineCSS(ref initialXmlDoc); + + Assert.IsTrue(XmlDocComparator.AreIdentical(initialXmlDoc, expectedXmlDoc)); + } + + /// + /// Tests the InlineCSS method. Several properties for a CSS class are specified + /// in different rules. Some selectors are grouped. The style for the CSS class + /// should be inlined. + /// + [Test] + public void TestInlineCSSMoreRules() + { + initialXmlDoc = new XmlDocument(); + expectedXmlDoc = new XmlDocument(); + + initialHTML = "TITLE" + + "" + + "" + + "" + + "

Some text

" + + ""; + + expectedHTML = "TITLE" + + "" + + "" + + "" + + "

Some text

" + + ""; + + initialXmlDoc.LoadXml(initialHTML); + expectedXmlDoc.LoadXml(expectedHTML); + + CSSUtil.InlineCSS(ref initialXmlDoc); + Assert.IsTrue(XmlDocComparator.AreIdentical(initialXmlDoc, expectedXmlDoc)); + } + + /// /// Performs a stress test for InlineCSS method: 15000 CSS classes and 15000 CSS ids for 30000 nodes. /// [Test] @@ -256,7 +341,7 @@ initialXmlDoc.LoadXml(initialHTML); - expectedHTML="TITLE" + expectedHTML = "TITLE" + "" + "
" + "

Text 1

" @@ -294,7 +379,7 @@ //6 CSS classes from .xoffice0 to .xoffice5 for (int i = 0; i < 6; i++) { - + Assert.IsTrue(cssClasses.ContainsKey(".xoffice" + i)); } @@ -305,7 +390,7 @@ } } - - + + } }