Example #1
0
    public static string MoveCssInline(string htmlInput, bool removeStyleElements, Uri basePath)
    {
      using (var reader = new System.IO.StringReader(htmlInput))
      {
        var web = new System.Net.WebClient();
        var sgmlReader = new Pipes.Sgml.SgmlReader();
        sgmlReader.DocType = "HTML";
        sgmlReader.WhitespaceHandling = WhitespaceHandling.All;
        sgmlReader.CaseFolding = CaseFolding.ToLower;
        sgmlReader.InputStream = reader;
        sgmlReader.SimulatedNode = "html";
        sgmlReader.StripDocType = false;
        
        var doc = new XmlDocument();
        doc.Load(sgmlReader);
        var root = doc.DocumentElement;
        if (root.ChildNodes.OfType<XmlElement>().Count() == 1) root = root.ChildNodes.OfType<XmlElement>().Single();

        var parser = new Parser();
        var engine = new HtmlQueryEngine();
        var visitor = new MatchVisitor(engine) { Comparison = StringComparison.OrdinalIgnoreCase };

        var css = new StringBuilder();
        var nodes = doc.SelectNodes("//style").OfType<System.Xml.XmlNode>().ToList();
        foreach (var node in nodes)
        {
          css.AppendLine(node.InnerText);
          if (removeStyleElements) node.ParentNode.RemoveChild(node);
        }

        nodes = doc.SelectNodes("//link[@rel='stylesheet' and @href]").OfType<System.Xml.XmlNode>().ToList();
        foreach (var node in nodes)
        {
          css.Append("@import url('").Append(node.Attributes["href"].Value).Append("')");
          if (node.Attributes["media"] != null && !string.IsNullOrEmpty(node.Attributes["media"].Value))
          {
            css.Append(" ").Append(node.Attributes["media"].Value);
          }
          css.AppendLine(";");
          if (removeStyleElements) node.ParentNode.RemoveChild(node);
        }

        var stylesheet = parser.Parse(css.ToString());
        var elements = root.SelectNodes("//*").OfType<XmlElement>().Select(e => new Pipes.Xml.XmlElementWrapper(e)).ToList();
        var settings = new GlobalStyleContext();
        settings.ResourceLoader = p => {
          var href = (basePath == null ? new Uri(p) : new Uri(basePath, p));
          return DownloadStream(href);
        };

        var rules = stylesheet.Rules.GetStyleRules(settings).ToList();
        IEnumerable<StyleRule> elemRules;
        string inlineStyle;
        IEnumerable<Property> props;
        foreach (var elem in elements)
        {
          inlineStyle = elem.Attribute<string>("style", null);
          elemRules = rules;
          if (!string.IsNullOrEmpty(inlineStyle))
          {
            elemRules = elemRules.Concat(Enumerable.Repeat(Utils.ParseInline(inlineStyle), 1));
          }
          props = elemRules.ApplicableProperties(elem, engine, StringComparison.OrdinalIgnoreCase, settings);
          if (props.Any())
          {
            inlineStyle = props.Select(p => p.ToString()).Aggregate((p, c) => p + ";" + c);
            elem.Attribute("style", inlineStyle);
          }
        }

        return doc.OuterXml;
      }
    }
Example #2
0
 public void Visit(PseudoFunction selector)
 {
   switch (selector.Type)
   {
     case PseudoTypes.FunctionNot:
       var visitor = new MatchVisitor(new HtmlQueryEngine());
       var sel = selector.Body as ISelector;
       _matches = _matches.Where(n =>
       {
         visitor.Initialize(n);
         sel.Visit(visitor);
         return !visitor.IsMatch();
       });
       break;
     case PseudoTypes.FunctionContains:
     case PseudoTypes.FunctionDir:
     default:
       NotSupported();
       break;
   }
 }
Example #3
0
    public static IEnumerable<Property> ApplicableProperties(this IEnumerable<StyleRule> rules, IQueryableNode node, IQueryEngine engine, StringComparison comparison, GlobalStyleContext settings)
    {
      var visitor = new MatchVisitor(engine);
      visitor.Comparison = comparison;
      var terms = new Dictionary<string, TermSpecificity>();
      TermSpecificity existing;
      int specificity = 0;
      int propSpecificity;

      foreach (var style in rules)
      {
        if (style.Selector != null)
        {
          visitor.Initialize(node);
          style.Selector.Visit(visitor);
        }
        if (style.Selector == null || visitor.IsMatch())
        {
          specificity = style.Selector == null ? 0 : (visitor.MatchSpecificity > 0 ? visitor.MatchSpecificity : style.Selector.GetSpecificity());
          foreach (var prop in style.Declarations.SelectMany(p => p.Expand(settings.LeftToRight)))
          {
            propSpecificity = specificity + (prop.Important ? (1 << 20) : 0);
            if (terms.TryGetValue(prop.Name, out existing))
            {
              if (propSpecificity >= existing.Specificity)
              {
                existing.Property = prop;
              }
            }
            else
            {
              terms[prop.Name] = new TermSpecificity() { Property = prop, Specificity = propSpecificity };
            }
          }
        }
      }

      return terms.Values.Select(v => v.Property);
    }