private Dictionary <IElement, List <StyleClass> > SortBySpecificity( Dictionary <IElement, List <StyleClass> > styles) { var result = new Dictionary <IElement, List <StyleClass> >(); foreach (var style in styles) { if (style.Key.Attributes != null) { var sortedStyles = style.Value.OrderBy(x => _cssSelectorParser.GetSelectorSpecificity(x.Name)).ThenBy(x => x.Position).ToList(); var styleAttr = style.Key.Attributes["style"]; if (styleAttr == null || String.IsNullOrWhiteSpace(styleAttr.Value)) { style.Key.SetAttribute("style", String.Empty); } else // Ensure that existing inline styles always win. { sortedStyles.Add(_cssParser.ParseStyleClass("inline", styleAttr.Value)); } result[style.Key] = sortedStyles; } } return(result); }
/// <summary> /// Moves the CSS embedded in the specified htmlInput to inline style attributes. /// </summary> /// <param name="htmlInput">The HTML input.</param> /// <param name="removeStyleElements">if set to <c>true</c> the style elements are removed.</param> /// <returns>Returns the html input, with styles moved to inline attributes.</returns> public string MoveCssInline(string htmlInput, bool removeStyleElements) { var doc = CQ.CreateDocument(htmlInput); var styleNodes = doc["style"]; if (styleNodes == null || styleNodes.Length == 0) { return(htmlInput); // no styles to move } foreach (var style in styleNodes) { if (style.Attributes["id"] != null && !String.IsNullOrWhiteSpace(style.Attributes["id"]) && style.Attributes["id"].Equals("mobile", StringComparison.InvariantCultureIgnoreCase)) { continue; } var cssParser = new CssParser(); string cssBlock = style.InnerHTML; cssParser.AddStyleSheet(cssBlock); foreach (var rule in cssParser.Styles) { if (rule.Key.StartsWith("@media")) { continue; } var styleClass = rule.Value; var elements = doc[styleClass.Name]; foreach (var element in elements) { if (_elementsWithoutStyle.Contains(element.NodeName.ToLower())) { continue; } var elementStyle = element.Style; if (elementStyle == null) { continue; } StyleClass sc = cssParser.ParseStyleClass("dummy", elementStyle.CssText ?? String.Empty); sc.Merge(styleClass, true); foreach (var attr in sc.Attributes) { elementStyle.SetStyle(attr.Key, attr.Value, false); } } } if (removeStyleElements) { style.Remove(); } } return(doc.Render()); }
/// <summary> /// Moves the CSS embedded in the specified htmlInput to inline style attributes. /// </summary> /// <param name="htmlInput">The HTML input.</param> /// <param name="removeStyleElements">if set to <c>true</c> the style elements are removed.</param> /// <returns>Returns the html input, with styles moved to inline attributes.</returns> public string MoveCssInline(string htmlInput, bool removeStyleElements) { HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(htmlInput); var styleNodes = doc.DocumentNode.SelectNodes("//style"); if (styleNodes == null) { return(htmlInput); // no styles to move } foreach (var style in styleNodes) { if (style.Attributes["id"] != null && !String.IsNullOrWhiteSpace(style.Attributes["id"].Value) && style.Attributes["id"].Value.Equals("mobile", StringComparison.InvariantCultureIgnoreCase)) { continue; } CssParser cssParser = new CssParser(); string cssBlock = style.InnerHtml; cssParser.AddStyleSheet(cssBlock); foreach (var item in cssParser.Styles) { var styleClass = item.Value; var elements = doc.DocumentNode.QuerySelectorAll(styleClass.Name); foreach (var element in elements) { HtmlAttribute styleAttribute = element.Attributes["style"]; if (styleAttribute == null) { element.Attributes.Add("style", String.Empty); styleAttribute = element.Attributes["style"]; } StyleClass sc = cssParser.ParseStyleClass("dummy", styleAttribute.Value); sc.Merge(styleClass, false); styleAttribute.Value = sc.ToString(); } } if (removeStyleElements) { style.Remove(); } } return(doc.DocumentNode.OuterHtml); }
/// <summary> /// Moves the CSS embedded in the specified htmlInput to inline style attributes. /// </summary> /// <param name="htmlInput">The HTML input.</param> /// <param name="removeStyleElements">if set to <c>true</c> the style elements are removed.</param> /// <returns>Returns the html input, with styles moved to inline attributes.</returns> public string MoveCssInline(string htmlInput, bool removeStyleElements) { HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(htmlInput); var styleNodes = doc.DocumentNode.SelectNodes("//style"); if (styleNodes == null) return htmlInput; // no styles to move foreach (var style in styleNodes) { if (style.Attributes["id"] != null && !String.IsNullOrWhiteSpace(style.Attributes["id"].Value) && style.Attributes["id"].Value.Equals("mobile", StringComparison.InvariantCultureIgnoreCase)) { continue; } CssParser cssParser = new CssParser(); string cssBlock = style.InnerHtml; cssParser.AddStyleSheet(cssBlock); foreach (var item in cssParser.Styles) { var styleClass = item.Value; var elements = doc.DocumentNode.QuerySelectorAll(styleClass.Name); foreach (var element in elements) { HtmlAttribute styleAttribute = element.Attributes["style"]; if (styleAttribute == null) { element.Attributes.Add("style", String.Empty); styleAttribute = element.Attributes["style"]; } StyleClass sc = cssParser.ParseStyleClass("dummy", styleAttribute.Value); sc.Merge(styleClass, true); styleAttribute.Value = sc.ToString(); } } if (removeStyleElements) { style.Remove(); } } return doc.DocumentNode.OuterHtml; }