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)); }
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)); } }
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); } }
/// <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; }
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; }
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; }
/// <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); }
/// <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; }
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); } }
// //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)); }
/**************************************************************************/ 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); } }