示例#1
0
        public void TestSelectorSpecificity(string selector, int specificity)
        {
            var parser = new ExCSS.Parser();
            var sheet  = parser.Parse(selector + " {color:black}");

            Assert.Equal(specificity, CssQuery.GetSpecificity(sheet.StyleRules[0].Selector));
        }
示例#2
0
        public void Analyze(string css)
        {
            var parsedCss = new Parser().Parse(css);
            foreach (var rule in parsedCss.Ruleset.OfType<StyleRule>())
            {
                var selectors = new List<string>();
                
                var selectorList = rule.Selector as MultipleSelectorList;
                if (selectorList != null)
                {
                    selectors.AddRange(selectorList.Select(selector => selector.ToString()));
                }
                else
                {
                    selectors.Add(rule.Selector.ToString());
                }

                var rules = new Dictionary<string, string>();
                foreach (var declaration in rule.Declarations)
                {
                    rules[declaration.Name] = declaration.Term.ToString();
                }

                Rules.Add(new CssRule(selectors, rules));
            }
        }
示例#3
0
 protected override void Load(string path)
 {
     using (var reader = new StreamReader(path, true))
     {
         var parser = new ExCSS.Parser();
         _styleSheet = parser.Parse(reader.ReadToEnd());
         _encoding   = reader.CurrentEncoding;
     }
 }
        public void TestBadCss()
        {
            StylesheetParser ExCssParser = new StylesheetParser();

            foreach (string Filename in CssBadDocs.Keys)
            {
                string     CssData       = CssBadDocs[Filename];
                Stylesheet CssStylesheet = ExCssParser.Parse(CssData);
                Assert.IsNotNull(CssStylesheet, string.Format("FAIL: {0}", Filename));
            }
        }
示例#5
0
        public static void Obfuscate(string input, string output, Obfuscator ob)
        {
            var p = new ExCSS.Parser();
            var stylesheet = p.Parse(File.ReadAllText(input, Encoding.UTF8));
            var co = new CssObfuscator(stylesheet, ob);
            co.Obfuscate();

            if (output != null)
            {
                string css = stylesheet.ToString();
                File.WriteAllText(output, css, Encoding.UTF8);
            }
        }
示例#6
0
        /// <summary>
        /// Parses the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns></returns>
        public Stylesheet Parse(Stream stream)
        {
            Errors.Clear();

            var builder = new StringBuilder();
            var errorStream = new StringWriter(builder);
            var scanner = new Scanner(stream);
            var parser = new Parser(scanner)
            {
                errors =
                {
                    errorStream = errorStream
                }
            };

            parser.Parse();
            Stylesheet = parser.Stylesheet;
            SpitErrors(builder);
            return Stylesheet;
        }
示例#7
0
        public IList<IconsSet> GetIcons()
        {
            string path = Path.Combine(_pathHelper.GetContentDirectory(), "css", "fonts");

            var parser = new Parser();

            var list = new List<IconsSet>();

            foreach (var fileContent in Directory.GetFiles(path, "*.css")
                .Select(x => File.ReadAllText(x, Encoding.Default)))
            {
                var stylesheet = parser.Parse(fileContent);

                IconsSet set = new IconsSet
                                   {
                                       Icons =
                                           stylesheet.StyleRules.Select(x => x.Selector.ToString())
                                           .Where(x => x.Contains(":before"))
                                           .Select(x => x.Replace(":before", string.Empty))
                                           .Select(
                                               x =>
                                               string.Format(
                                                   "{0} {1}",
                                                   x.Split(new[] { '.', '-' })[1],
                                                   x.Replace(".", string.Empty)))
                                           .ToList(),
                                       Title =
                                           fileContent.Split(new[] { '\r', '\n' })
                                           .FirstOrDefault()
                                           .With(x => Regex.Match(x, @"/\*(.*?)\*/").Groups[1].Value)
                                   };

                list.Add(set);
            }

            return list;
        }
示例#8
0
        public IEnumerable<string> Parse(Stream stream)
        {
            var files = new List<string>();
            var parser = new Parser();
            var stylesheet = parser.Parse(stream);

            var file = new StringBuilder();
            var index = 0;
            foreach (StyleRule rule in stylesheet.Rulesets)
            {
                if (index >= MaxSelectorCount)
                {
                    index = 0;
                    files.Add(file.ToString());
                    file = new StringBuilder();
                }

                file.AppendLine(rule.ToString());
                index++;
            }
            files.Add(file.ToString().TrimEnd());

            return files;
        }
示例#9
0
        /// <summary>
        /// Accepts a string of HTML and produces a string of HTML with styles inlined.
        /// </summary>
        /// <param name="sourceHtml"></param>
        /// <returns></returns>
        public static String ProcessHtml(string sourceHtml)
        {
            var document = CQ.CreateDocument(sourceHtml);

            //Console.WriteLine(document.Document.DocType);

            foreach (var s in document["script"].Elements)
            {
                s.Remove();
            }

            var sheets = document["style"].Elements.OfType <HTMLStyleElement>().ToArray();

            var parser            = new ExCSS.Parser();
            var parsedStylesheets = new List <Tuple <HTMLStyleElement, StyleSheet> >();

            foreach (var k in sheets)
            {
                try
                {
                    parsedStylesheets.Add(Tuple.Create(k, parser.Parse(k.InnerHTML)));
                }
                catch
                {
                    throw new InliningException("Not all stylesheet declarations in stylesheet beginning with '" + k.InnerHTML.Substring(0, 100) + "...' could be parsed.");
                }
            }

            var normalRules    = new List <RuleTuple>();
            var importantRules = new List <RuleTuple>();


            //YIKES! this is hideous, but it's OK, it'll do what we need.
            var ruleIndex = 0;

            foreach (var styleSheet in parsedStylesheets)
            {
                var uninlineable = new List <Tuple <string, StyleDeclaration> >();

                var styleRules = styleSheet.Item2.StyleRules.Where(s => s.Selector != null).ToArray();
                foreach (var s in styleRules)
                {
                    var selectors = s.Selector.ToString().Split(',').ToLookup(k => true);
                    // MOST of the time, the selector isn't going to match.
                    // Therefore, we avoid regexing each selector in the string
                    // for only those cases where it does match.
                    if (_pseudoclassSelector.IsMatch(s.Selector.ToString()))
                    {
                        selectors = s.Selector.ToString().Split(',').ToLookup(k => !_pseudoclassSelector.IsMatch(k));
                    }

                    var importantAndNot = s.Declarations.ToLookup(k => k.Important);

                    //inline the safe rules per normal.
                    foreach (var selector in selectors[true])
                    {
                        ruleIndex++;
                        normalRules.Add(new RuleTuple()
                        {
                            DocumentOrder = ruleIndex,
                            Declarations  = importantAndNot[false]
                                            .Aggregate("", (seed, current) => seed += String.Format("{0}:{1};", current.Name, current.Term)),
                            Selector    = selector,
                            Specificity = selector.Specificity()
                        });
                        importantRules.Add(new RuleTuple()
                        {
                            DocumentOrder = ruleIndex,
                            Declarations  = importantAndNot[true]
                                            .Aggregate("", (seed, current) => seed += String.Format("{0}:{1} !important;", current.Name, current.Term)),
                            Selector    = selector,
                            Specificity = new Specificity()
                        });
                    }

                    if (selectors[false].Any())
                    {
                        uninlineable.Add(Tuple.Create(String.Join(",", selectors[false]), s.Declarations));
                    }
                }

                //scrub all rules from the stylesheet.
                styleSheet.Item2.Rules.RemoveAll(k => k is StyleRule);

                //if there are "left over" rules, we want to make sure those are applied.
                foreach (var i in uninlineable)
                {
                    foreach (var d in i.Item2)
                    {
                        d.Important = true;
                    }

                    styleSheet.Item2.Rules.Add(new StyleRule(i.Item2)
                    {
                        Value = i.Item1
                    });
                }

                //apply the stylesheet content back to the CsQuery object.
                if (styleSheet.Item2.Rules.Any())
                {
                    styleSheet.Item1.InnerText = styleSheet.Item2.ToString();
                }
                else
                {
                    styleSheet.Item1.Remove();
                }
            }


            var noApplyElements = new HashSet <IDomElement>(document.Select("head").Elements.SelectMany(k => GetAllChildren(k)));

            ApplyRulesToElements(document, normalRules, noApplyElements);
            ApplyRulesToElements(document, importantRules, noApplyElements);

            //fix to original doctype
            var processed = document.Render();
            var m         = _doctypeFinder.Match(sourceHtml);

            if (m.Success)
            {
                processed = _doctypeFinder.Replace(processed, m.Value);
            }

            return(processed);
        }
示例#10
0
        /// <summary>
        /// Accepts a string of HTML and produces a string of HTML with styles inlined.
        /// </summary>
        /// <param name="sourceHtml"></param>
        /// <returns></returns>
        public static String ProcessHtml(string sourceHtml)
        {
            var document = CQ.CreateDocument(sourceHtml);

            //Console.WriteLine(document.Document.DocType);

            foreach (var s in document["script"].Elements)
            {
                s.Remove();
            }

            var sheets = document["style"].Elements.OfType<HTMLStyleElement>().ToArray();

            var parser = new ExCSS.Parser();
            var parsedStylesheets = new List<Tuple<HTMLStyleElement, StyleSheet>>();

            foreach (var k in sheets)
            {
                try
                {
                    parsedStylesheets.Add(Tuple.Create(k, parser.Parse(k.InnerHTML)));
                }
                catch
                {
                    throw new InliningException("Not all stylesheet declarations in stylesheet beginning with '" + k.InnerHTML.Substring(0, 100) + "...' could be parsed.");
                }
            }

            var normalRules = new List<RuleTuple>();
            var importantRules = new List<RuleTuple>();

            //YIKES! this is hideous, but it's OK, it'll do what we need.
            var ruleIndex = 0;
            foreach (var styleSheet in parsedStylesheets)
            {
                var uninlineable = new List<Tuple<string, StyleDeclaration>>();

                var styleRules = styleSheet.Item2.StyleRules.ToArray();
                foreach (var s in styleRules)
                {
                    var selectors = s.Selector.ToString().Split(',').ToLookup(k => true);
                    // MOST of the time, the selector isn't going to match.
                    // Therefore, we avoid regexing each selector in the string
                    // for only those cases where it does match.
                    if (_pseudoclassSelector.IsMatch(s.Selector.ToString()))
                    {
                        selectors = s.Selector.ToString().Split(',').ToLookup(k => !_pseudoclassSelector.IsMatch(k));
                    }

                    var importantAndNot = s.Declarations.ToLookup(k => k.Important);

                    //inline the safe rules per normal.
                    foreach (var selector in selectors[true])
                    {
                        ruleIndex++;
                        normalRules.Add(new RuleTuple()
                        {
                            DocumentOrder = ruleIndex,
                            Declarations = importantAndNot[false]
                                .Aggregate("", (seed, current) => seed += String.Format("{0}:{1};", current.Name, current.Term)),
                            Selector = selector,
                            Specificity = selector.Specificity()
                        });
                        importantRules.Add(new RuleTuple()
                        {
                            DocumentOrder = ruleIndex,
                            Declarations = importantAndNot[true]
                                .Aggregate("", (seed, current) => seed += String.Format("{0}:{1} !important;", current.Name, current.Term)),
                            Selector = selector,
                            Specificity = new Specificity()
                        });
                    }

                    if (selectors[false].Any())
                    {
                        uninlineable.Add(Tuple.Create(String.Join(",", selectors[false]), s.Declarations));
                    }
                }

                //scrub all rules from the stylesheet.
                styleSheet.Item2.Rules.RemoveAll(k => k is StyleRule);

                //if there are "left over" rules, we want to make sure those are applied.
                foreach (var i in uninlineable)
                {
                    foreach (var d in i.Item2)
                    {
                        d.Important = true;
                    }

                    styleSheet.Item2.Rules.Add(new StyleRule(i.Item2)
                    {
                        Value = i.Item1
                    });
                }

                //apply the stylesheet content back to the CsQuery object.
                if (styleSheet.Item2.Rules.Any())
                {
                    styleSheet.Item1.InnerText = styleSheet.Item2.ToString();
                }
                else
                {
                    styleSheet.Item1.Remove();
                }
            }

            var noApplyElements = new HashSet<IDomElement>(document.Select("head").Elements.SelectMany(k => GetAllChildren(k)));

            ApplyRulesToElements(document, normalRules, noApplyElements);
            ApplyRulesToElements(document, importantRules, noApplyElements);

            //fix to original doctype
            var processed = document.Render();
            var m = _doctypeFinder.Match(sourceHtml);
            if (m.Success)
            {
                processed = _doctypeFinder.Replace(processed, m.Value);
            }

            return processed;
        }
示例#11
0
 public void Run(String source)
 {
     var parser = new Parser();
     parser.Parse(source);
 }
        /** -------------------------------------------------------------------- **/

        private async Task _ProcessCssPage()
        {
            MacroscopeHttpTwoClient         Client   = this.DocCollection.GetJobMaster().GetHttpClient();
            MacroscopeHttpTwoClientResponse Response = null;
            string ResponseErrorCondition            = null;

            DebugMsg(string.Format("ProcessCssPage: {0}", ""));

            try
            {
                Response = await Client.Get(
                    this.GetUri(),
                    this.ConfigureCssPageRequestHeadersCallback,
                    this.PostProcessRequestHttpHeadersCallback
                    );
            }
            catch (MacroscopeDocumentException ex)
            {
                this.DebugMsg(string.Format("_ProcessCssPage :: MacroscopeDocumentException: {0}", ex.Message));
                ResponseErrorCondition = ex.Message;
                this.SetStatusCode(HttpStatusCode.BadRequest);
                this.AddRemark("_ProcessCssPage", ex.Message);
            }
            catch (Exception ex)
            {
                this.DebugMsg(string.Format("_ProcessCssPage :: Exception: {0}", ex.Message));
                ResponseErrorCondition = ex.Message;
                this.SetStatusCode(HttpStatusCode.BadRequest);
                this.AddRemark("_ProcessCssPage", ex.Message);
            }

            if (Response != null)
            {
                string RawData = "";

                this.ProcessResponseHttpHeaders(Response: Response);

                /** Get Response Body ---------------------------------------------- **/

                try
                {
                    DebugMsg(string.Format("MIME TYPE: {0}", this.MimeType));

                    RawData = Response.GetContentAsString();

                    this.SetContentLength(Length: RawData.Length); // May need to find bytes length

                    this.SetWasDownloaded(true);
                }
                catch (Exception ex)
                {
                    DebugMsg(string.Format("Exception: {0}", ex.Message));
                    this.SetStatusCode(HttpStatusCode.Ambiguous);
                    this.SetContentLength(Length: 0);
                }

                if (!string.IsNullOrEmpty(RawData))
                {
                    try
                    {
                        StylesheetParser CssParser     = new StylesheetParser();
                        Stylesheet       CssStylesheet = CssParser.Parse(RawData);
                        this.ProcessCssOutlinks(CssStylesheet: CssStylesheet);
                    }
                    catch (Exception ex)
                    {
                        this.DebugMsg(string.Format("ProcessHtmlAttributeCssLinks: {0}", ex.Message));
                        this.AddRemark("ProcessHtmlAttributeCssLinks", ex.Message);
                    }
                }
                else
                {
                    DebugMsg(string.Format("ProcessCssPage: ERROR: {0}", this.GetUrl()));
                }

                /** Custom Filters ------------------------------------------------- **/

                if (!string.IsNullOrEmpty(RawData))
                {
                    if (
                        MacroscopePreferencesManager.GetCustomFiltersEnable() &&
                        MacroscopePreferencesManager.GetCustomFiltersApplyToCss())
                    {
                        MacroscopeCustomFilters CustomFilter = this.DocCollection.GetJobMaster().GetCustomFilter();

                        if ((CustomFilter != null) && (CustomFilter.IsEnabled()))
                        {
                            this.ProcessGenericCustomFiltered(
                                CustomFilter: CustomFilter,
                                GenericText: RawData
                                );
                        }
                    }
                }

                /** Data Extractors ------------------------------------------------ **/

                if (!string.IsNullOrEmpty(RawData))
                {
                    if (
                        MacroscopePreferencesManager.GetDataExtractorsEnable() &&
                        MacroscopePreferencesManager.GetDataExtractorsApplyToCss())
                    {
                        this.ProcessGenericDataExtractors(GenericText: RawData);
                    }
                }

                /** Title ---------------------------------------------------------- **/

                {
                    MatchCollection reMatches     = Regex.Matches(this.DocUrl, "/([^/]+)$");
                    string          DocumentTitle = null;
                    foreach (Match match in reMatches)
                    {
                        if (match.Groups[1].Value.Length > 0)
                        {
                            DocumentTitle = match.Groups[1].Value.ToString();
                            break;
                        }
                    }
                    if (DocumentTitle != null)
                    {
                        this.SetTitle(DocumentTitle, MacroscopeConstants.TextProcessingMode.NO_PROCESSING);
                        DebugMsg(string.Format("TITLE: {0}", this.GetTitle()));
                    }
                    else
                    {
                        DebugMsg(string.Format("TITLE: {0}", "MISSING"));
                    }
                }
            }

            if (ResponseErrorCondition != null)
            {
                this.ProcessErrorCondition(ResponseErrorCondition);
            }
        }
示例#13
0
 // 
 //You can use the following additional attributes as you write your tests:
 //
 //Use ClassInitialize to run code before running the first test in the class
 //[ClassInitialize()]
 //public static void MyClassInitialize(TestContext testContext)
 //{
 //}
 //
 //Use ClassCleanup to run code after all tests in a class have run
 //[ClassCleanup()]
 //public static void MyClassCleanup()
 //{
 //}
 //
 //Use TestInitialize to run code before running each test
 //[TestInitialize()]
 //public void MyTestInitialize()
 //{
 //}
 //
 //Use TestCleanup to run code after each test has run
 //[TestCleanup()]
 //public void MyTestCleanup()
 //{
 //}
 //
 #endregion
 
 private void TestSelectorSpecificity(string selector, int specificity)
 {
     var parser = new ExCSS.Parser();
     var sheet = parser.Parse(selector + " {color:black}");
     Assert.AreEqual(specificity, CssQuery.GetSpecificity(sheet.StyleRules[0].Selector));
 }
示例#14
0
        /**************************************************************************/

        private void ProcessCssPage()
        {
            HttpWebRequest  req = null;
            HttpWebResponse res = null;
            string          ResponseErrorCondition = null;
            Boolean         IsAuthenticating       = false;

            DebugMsg(string.Format("ProcessCssPage: {0}", ""));

            try
            {
                req           = WebRequest.CreateHttp(this.DocUrl);
                req.Method    = "GET";
                req.Timeout   = this.Timeout;
                req.KeepAlive = false;
                req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

                this.PrepareRequestHttpHeaders(req: req);

                IsAuthenticating = this.AuthenticateRequest(req);

                MacroscopePreferencesManager.EnableHttpProxy(req);

                res = ( HttpWebResponse )req.GetResponse();
            }
            catch (UriFormatException ex)
            {
                DebugMsg(string.Format("ProcessCssPage :: UriFormatException: {0}", ex.Message));
                ResponseErrorCondition = ex.Message;
            }
            catch (TimeoutException ex)
            {
                DebugMsg(string.Format("ProcessCssPage :: TimeoutException: {0}", ex.Message));
                ResponseErrorCondition = ex.Message;
            }
            catch (WebException ex)
            {
                DebugMsg(string.Format("ProcessCssPage :: WebException: {0}", ex.Message));
                DebugMsg(string.Format("ProcessCssPage :: WebException: {0}", ex.Status));
                DebugMsg(string.Format("ProcessCssPage :: WebException: {0}", ( int )ex.Status));

                ResponseErrorCondition = ex.Status.ToString();
            }

            if (res != null)
            {
                string RawData = "";

                this.ProcessResponseHttpHeaders(req, res);

                if (IsAuthenticating)
                {
                    this.VerifyOrPurgeCredential();
                }

                // Get Response Body
                try
                {
                    DebugMsg(string.Format("MIME TYPE: {0}", this.MimeType));

                    Stream       ResponseStream = res.GetResponseStream();
                    StreamReader ResponseStreamReader;

                    if (this.GetCharacterEncoding() != null)
                    {
                        ResponseStreamReader = new StreamReader(ResponseStream, this.GetCharacterEncoding());
                    }
                    else
                    {
                        ResponseStreamReader = new StreamReader(ResponseStream);
                    }

                    RawData = ResponseStreamReader.ReadToEnd();

                    this.ContentLength = RawData.Length; // May need to find bytes length

                    this.SetWasDownloaded(true);
                }
                catch (WebException ex)
                {
                    DebugMsg(string.Format("WebException: {0}", ex.Message));

                    if (ex.Response != null)
                    {
                        this.SetStatusCode((( HttpWebResponse )ex.Response).StatusCode);
                    }
                    else
                    {
                        this.SetStatusCode(( HttpStatusCode )ex.Status);
                    }

                    RawData            = "";
                    this.ContentLength = 0;
                }
                catch (Exception ex)
                {
                    DebugMsg(string.Format("Exception: {0}", ex.Message));
                    this.SetStatusCode(HttpStatusCode.BadRequest);
                    this.ContentLength = 0;
                }

                if (!string.IsNullOrEmpty(RawData))
                {
                    ExCSS.Parser     ExCssParser     = new ExCSS.Parser();
                    ExCSS.StyleSheet ExCssStylesheet = ExCssParser.Parse(RawData);

                    this.ProcessCssOutlinks(ExCssStylesheet);
                }
                else
                {
                    DebugMsg(string.Format("ProcessCssPage: ERROR: {0}", this.GetUrl()));
                }

                /** Custom Filters ------------------------------------------------- **/

                if (!string.IsNullOrEmpty(RawData))
                {
                    if (
                        MacroscopePreferencesManager.GetCustomFiltersEnable() &&
                        MacroscopePreferencesManager.GetCustomFiltersApplyToCss())
                    {
                        MacroscopeCustomFilters CustomFilter = this.DocCollection.GetJobMaster().GetCustomFilter();

                        if ((CustomFilter != null) && (CustomFilter.IsEnabled()))
                        {
                            this.ProcessGenericCustomFiltered(
                                CustomFilter: CustomFilter,
                                GenericText: RawData
                                );
                        }
                    }
                }

                /** Data Extractors ------------------------------------------------ **/

                if (!string.IsNullOrEmpty(RawData))
                {
                    if (
                        MacroscopePreferencesManager.GetDataExtractorsEnable() &&
                        MacroscopePreferencesManager.GetDataExtractorsApplyToCss())
                    {
                        this.ProcessGenericDataExtractors(GenericText: RawData);
                    }
                }

                /** Title ---------------------------------------------------------- **/

                {
                    MatchCollection reMatches     = Regex.Matches(this.DocUrl, "/([^/]+)$");
                    string          DocumentTitle = null;
                    foreach (Match match in reMatches)
                    {
                        if (match.Groups[1].Value.Length > 0)
                        {
                            DocumentTitle = match.Groups[1].Value.ToString();
                            break;
                        }
                    }
                    if (DocumentTitle != null)
                    {
                        this.SetTitle(DocumentTitle, MacroscopeConstants.TextProcessingMode.NO_PROCESSING);
                        DebugMsg(string.Format("TITLE: {0}", this.GetTitle()));
                    }
                    else
                    {
                        DebugMsg(string.Format("TITLE: {0}", "MISSING"));
                    }
                }

                res.Close();

                res.Dispose();
            }

            if (ResponseErrorCondition != null)
            {
                this.ProcessErrorCondition(ResponseErrorCondition);
            }
        }