public NthMatcherBase(CssNodeType type, string text) : base(type, text) { Text = GetParameterExpression(text); GetFactorAndDistance(Text, out factor, out distance); }
public AttributeMatcher(CssNodeType type, string text) : base(type, text) { var match = attributeMatcher.Match(text); if (match.Groups.Count > 1 && match.Groups[1].Success) { PropertyName = match.Groups[1].Value; } if (match.Groups.Count > 2 && match.Groups[2].Success) { Operator = match.Groups[2].Value; } if (match.Groups.Count > 3 && match.Groups[3].Success) { Value = match.Groups[3].Value.Trim('"'); } }
/// <summary> /// Transforms all relative paths to absolute in CSS code /// </summary> /// <param name="content">Text content of CSS asset</param> /// <param name="path">CSS file path</param> /// <returns>Processed text content of CSS asset</returns> public string ResolveAllRelativePaths(string content, string path) { int contentLength = content.Length; if (contentLength == 0) { return(content); } MatchCollection urlRuleMatches = CommonRegExps.CssUrlRuleRegex.Matches(content); MatchCollection importRuleMatches = _cssImportRuleRegex.Matches(content); if (urlRuleMatches.Count == 0 && importRuleMatches.Count == 0) { return(content); } var nodeMatches = new List <CssNodeMatch>(); foreach (Match urlRuleMatch in urlRuleMatches) { var nodeMatch = new CssNodeMatch(urlRuleMatch.Index, urlRuleMatch.Length, CssNodeType.UrlRule, urlRuleMatch); nodeMatches.Add(nodeMatch); } foreach (Match importRuleMatch in importRuleMatches) { var nodeMatch = new CssNodeMatch(importRuleMatch.Index, importRuleMatch.Length, CssNodeType.ImportRule, importRuleMatch); nodeMatches.Add(nodeMatch); } MatchCollection multilineCommentMatches = CommonRegExps.CssMultilineCommentRegex.Matches(content); foreach (Match multilineCommentMatch in multilineCommentMatches) { var nodeMatch = new CssNodeMatch(multilineCommentMatch.Index, multilineCommentMatch.Length, CssNodeType.MultilineComment, multilineCommentMatch); nodeMatches.Add(nodeMatch); } nodeMatches = nodeMatches .OrderBy(n => n.Position) .ThenByDescending(n => n.Length) .ToList() ; var contentBuilder = new StringBuilder(); int endPosition = contentLength - 1; int currentPosition = 0; foreach (CssNodeMatch nodeMatch in nodeMatches) { CssNodeType nodeType = nodeMatch.NodeType; int nodePosition = nodeMatch.Position; Match match = nodeMatch.Match; if (nodePosition < currentPosition) { continue; } if (nodeType == CssNodeType.UrlRule || nodeType == CssNodeType.ImportRule) { ProcessOtherContent(contentBuilder, content, ref currentPosition, nodePosition); if (nodeType == CssNodeType.UrlRule) { GroupCollection urlRuleGroups = match.Groups; string url = urlRuleGroups["url"].Value.Trim(); string quote = urlRuleGroups["quote"].Success ? urlRuleGroups["quote"].Value : string.Empty; string urlRule = match.Value; string processedUrlRule = ProcessUrlRule(path, url, quote); contentBuilder.Append(processedUrlRule); currentPosition += urlRule.Length; } else if (nodeType == CssNodeType.ImportRule) { GroupCollection importRuleGroups = match.Groups; string url = importRuleGroups["url"].Value.Trim(); string importRule = match.Value; string processedImportRule = ProcessImportRule(path, url); contentBuilder.Append(processedImportRule); currentPosition += importRule.Length; } } else if (nodeType == CssNodeType.MultilineComment) { int nextPosition = nodePosition + match.Length; ProcessOtherContent(contentBuilder, content, ref currentPosition, nextPosition); } } if (currentPosition > 0 && currentPosition <= endPosition) { ProcessOtherContent(contentBuilder, content, ref currentPosition, endPosition + 1); } return(contentBuilder.ToString()); }
public FirstChildMatcher(CssNodeType type, string text) : base(type, text) { }
public CssNode(CssNodeType type, CssNode parent, string text) { Type = type; Parent = parent; TextBuilder = new StringBuilder(text); }
public SelectorMatcher Create(CssNodeType type, string text) { if (type == CssNodeType.TypeSelector) { return(new TypeMatcher(type, text)); } else if (type == CssNodeType.ClassSelector) { return(new ClassMatcher(type, text)); } else if (type == CssNodeType.IdSelector) { return(new IdMatcher(type, text)); } else if (type == CssNodeType.UniversalSelector) { return(new UnivseralMatcher(type, text)); } else if (type == CssNodeType.PseudoSelector) { if (text.StartsWith(":nth-child", StringComparison.Ordinal)) { return(new NthChildMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":nth-of-type", StringComparison.Ordinal)) { return(new NthOfTypeMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":nth-last-child", StringComparison.Ordinal)) { return(new NthLastChildMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":nth-last-of-type", StringComparison.Ordinal)) { return(new NthLastOfTypeMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":first-child", StringComparison.Ordinal)) { return(new FirstChildMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":last-child", StringComparison.Ordinal)) { return(new LastChildMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":first-of-type", StringComparison.Ordinal)) { return(new FirstOfTypeMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":last-of-type", StringComparison.Ordinal)) { return(new LastOfTypeMatcher(CssNodeType.PseudoSelector, text)); } else if (text.StartsWith(":only-of-type", StringComparison.Ordinal)) { return(new OnlyOfTypeMatcher(CssNodeType.PseudoSelector, text)); } } else if (type == CssNodeType.InheritedTypeSelector) { return(new InheritedTypeMatcher(type, text)); } else if (type == CssNodeType.AttributeSelector) { return(new AttributeMatcher(CssNodeType.AttributeSelector, text)); } return(new SelectorMatcher(type, text)); }
/// <summary> /// Eject a <code>@charset</code> and <code>@import</code> rules /// </summary> /// <param name="content">Text content of style asset</param> /// <param name="topCharset">Processed top <code>@charset</code> rule</param> /// <param name="imports">List of processed <code>@import</code> rules</param> /// <returns>Text content of style asset without <code>@charset</code> and <code>@import</code> rules</returns> private static string EjectCssCharsetAndImports( string content, ref string topCharset, IList <string> imports) { int length = content.Length; if (length == 0) { return(content); } MatchCollection matchCollection1 = CommonRegExps.CssCharsetRuleRegex.Matches(content); MatchCollection matchCollection2 = StyleCombiner._cssImportRuleRegex.Matches(content); if (matchCollection1.Count == 0 && matchCollection2.Count == 0) { return(content); } List <CssNodeMatch> source = new List <CssNodeMatch>(); foreach (Match match in matchCollection1) { CssNodeMatch cssNodeMatch = new CssNodeMatch(match.Index, match.Length, CssNodeType.CharsetRule, match); source.Add(cssNodeMatch); } foreach (Match match in matchCollection2) { CssNodeMatch cssNodeMatch = new CssNodeMatch(match.Index, match.Length, CssNodeType.ImportRule, match); source.Add(cssNodeMatch); } foreach (Match match in CommonRegExps.CssMultilineCommentRegex.Matches(content)) { CssNodeMatch cssNodeMatch = new CssNodeMatch(match.Index, match.Length, CssNodeType.MultilineComment, match); source.Add(cssNodeMatch); } List <CssNodeMatch> list = source.OrderBy <CssNodeMatch, int>((Func <CssNodeMatch, int>)(n => n.Position)).ThenByDescending <CssNodeMatch, int>((Func <CssNodeMatch, int>)(n => n.Length)).ToList <CssNodeMatch>(); StringBuilderPool shared = StringBuilderPool.Shared; StringBuilder stringBuilder = shared.Rent(); int num = length - 1; int currentPosition = 0; foreach (CssNodeMatch cssNodeMatch in list) { CssNodeType nodeType = cssNodeMatch.NodeType; int position = cssNodeMatch.Position; Match match = cssNodeMatch.Match; if (position >= currentPosition) { switch (nodeType) { case CssNodeType.CharsetRule: case CssNodeType.ImportRule: StyleCombiner.ProcessOtherContent(stringBuilder, content, ref currentPosition, position); if (nodeType == CssNodeType.CharsetRule) { string str1 = match.Groups["charset"].Value; string str2 = match.Value; if (string.IsNullOrWhiteSpace(topCharset)) { topCharset = string.Format("@charset \"{0}\";", (object)str1); } currentPosition += str2.Length; continue; } if (nodeType == CssNodeType.ImportRule) { GroupCollection groups = match.Groups; string str1 = groups["url"].Value; string str2 = groups["media"].Success ? " " + groups["media"].Value : string.Empty; string str3 = match.Value; string str4 = string.Format("@import \"{0}\"{1};", (object)str1, (object)str2); imports.Add(str4); currentPosition += str3.Length; continue; } continue; case CssNodeType.MultilineComment: int nextPosition = position + match.Length; StyleCombiner.ProcessOtherContent(stringBuilder, content, ref currentPosition, nextPosition); continue; default: continue; } } } if (currentPosition > 0 && currentPosition <= num) { StyleCombiner.ProcessOtherContent(stringBuilder, content, ref currentPosition, num + 1); } string str = stringBuilder.ToString(); shared.Return(stringBuilder); return(str); }
public NthLastChildMatcher(CssNodeType type, string text) : base(type, text) { Text = text?.Substring(11).Replace(")", ""); }
/// <summary> /// Eject a <code>@charset</code> and <code>@import</code> rules /// </summary> /// <param name="content">Text content of style asset</param> /// <param name="topCharset">Processed top <code>@charset</code> rule</param> /// <param name="imports">List of processed <code>@import</code> rules</param> /// <returns>Text content of style asset without <code>@charset</code> and <code>@import</code> rules</returns> private static string EjectCssCharsetAndImports(string content, ref string topCharset, IList <string> imports) { int contentLength = content.Length; if (contentLength == 0) { return(content); } MatchCollection charsetRuleMatches = CommonRegExps.CssCharsetRuleRegex.Matches(content); MatchCollection importRuleMatches = _cssImportRuleRegex.Matches(content); if (charsetRuleMatches.Count == 0 && importRuleMatches.Count == 0) { return(content); } var nodeMatches = new List <CssNodeMatch>(); foreach (Match charsetRuleMatch in charsetRuleMatches) { var nodeMatch = new CssNodeMatch(charsetRuleMatch.Index, charsetRuleMatch.Length, CssNodeType.CharsetRule, charsetRuleMatch); nodeMatches.Add(nodeMatch); } foreach (Match importRuleMatch in importRuleMatches) { var nodeMatch = new CssNodeMatch(importRuleMatch.Index, importRuleMatch.Length, CssNodeType.ImportRule, importRuleMatch); nodeMatches.Add(nodeMatch); } MatchCollection multilineCommentMatches = CommonRegExps.CssMultilineCommentRegex.Matches(content); foreach (Match multilineCommentMatch in multilineCommentMatches) { var nodeMatch = new CssNodeMatch(multilineCommentMatch.Index, multilineCommentMatch.Length, CssNodeType.MultilineComment, multilineCommentMatch); nodeMatches.Add(nodeMatch); } nodeMatches = nodeMatches .OrderBy(n => n.Position) .ThenByDescending(n => n.Length) .ToList() ; var contentBuilder = new StringBuilder(); int endPosition = contentLength - 1; int currentPosition = 0; foreach (CssNodeMatch nodeMatch in nodeMatches) { CssNodeType nodeType = nodeMatch.NodeType; int nodePosition = nodeMatch.Position; Match match = nodeMatch.Match; if (nodePosition < currentPosition) { continue; } if (nodeType == CssNodeType.MultilineComment) { int nextPosition = nodePosition + match.Length; ProcessOtherContent(contentBuilder, content, ref currentPosition, nextPosition); } else if (nodeType == CssNodeType.CharsetRule || nodeType == CssNodeType.ImportRule) { ProcessOtherContent(contentBuilder, content, ref currentPosition, nodePosition); if (nodeType == CssNodeType.CharsetRule) { string charset = match.Groups["charset"].Value; string charsetRule = match.Value; if (string.IsNullOrWhiteSpace(topCharset)) { topCharset = string.Format(@"@charset ""{0}"";", charset); } currentPosition += charsetRule.Length; } else if (nodeType == CssNodeType.ImportRule) { GroupCollection importRuleGroups = match.Groups; string url = importRuleGroups["url"].Value; string media = importRuleGroups["media"].Success ? (" " + importRuleGroups["media"].Value) : string.Empty; string importRule = match.Value; string processedImportRule = string.Format(@"@import ""{0}""{1};", url, media); imports.Add(processedImportRule); currentPosition += importRule.Length; } } } if (currentPosition > 0 && currentPosition <= endPosition) { ProcessOtherContent(contentBuilder, content, ref currentPosition, endPosition + 1); } return(contentBuilder.ToString()); }
public InheritedTypeMatcher(CssNodeType type, string text) : base(type, text) { Text = text.Substring(1); }
public TypeMatcher(CssNodeType type, string text) : base(type, text) { }
/// <summary>Constructs a instance of CSS node match</summary> /// <param name="position">Position in the original string where /// the first character of the captured substring was found</param> /// <param name="length">Length of the captured substring</param> /// <param name="nodeType">Type of CSS node</param> /// <param name="match">Single regular expression match</param> public CssNodeMatch(int position, int length, CssNodeType nodeType, Match match) : base(position, length, match) => this.NodeType = nodeType;
public UnivseralMatcher(CssNodeType type, string text) : base(type, text) { }
public CssNode(CssNodeType type) { Type = type; TextBuilder = new StringBuilder(); }
public SelectorMatcher(CssNodeType type, string text) { Type = type; Text = text; }
private static List <TriggerAction> GetTriggerActions(CssNode astTriggerStyleDeclarationBlock, CssNodeType type, IDictionary <string, string> parameterValues) { if (type != CssNodeType.EnterAction && type != CssNodeType.ExitAction) { throw new InvalidOperationException("Type must be either EnterAction or ExitAction"); } var actionDeclarationBlockAst = astTriggerStyleDeclarationBlock.Children .Where(y => y.Type == type) .SelectMany(y => y.Children) .Where(y => y.Type == CssNodeType.ActionDeclarationBlock) .SingleOrDefault(); if (actionDeclarationBlockAst == null) { return(new List <TriggerAction>()); } return(GetActionDeclarationsFromBlock(actionDeclarationBlockAst, parameterValues)); }
/// <summary> /// Ejects a <code>@charset</code> rules /// </summary> /// <param name="content">Text content of CSS asset</param> /// <param name="topCharset">Processed top <code>@charset</code> rule</param> /// <returns>Text content of CSS asset without <code>@charset</code> rules</returns> private static string EjectCssCharset(string content, ref string topCharset) { int contentLength = content.Length; if (contentLength == 0) { return(content); } MatchCollection charsetRuleMatches = CommonRegExps.CssCharsetRuleRegex.Matches(content); if (charsetRuleMatches.Count == 0) { return(content); } var nodeMatches = new List <CssNodeMatch>(); foreach (Match charsetRuleMatch in charsetRuleMatches) { var nodeMatch = new CssNodeMatch(charsetRuleMatch.Index, charsetRuleMatch.Length, CssNodeType.CharsetRule, charsetRuleMatch); nodeMatches.Add(nodeMatch); } MatchCollection multilineCommentMatches = CommonRegExps.CssMultilineCommentRegex.Matches(content); foreach (Match multilineCommentMatch in multilineCommentMatches) { var nodeMatch = new CssNodeMatch(multilineCommentMatch.Index, multilineCommentMatch.Length, CssNodeType.MultilineComment, multilineCommentMatch); nodeMatches.Add(nodeMatch); } nodeMatches = nodeMatches .OrderBy(n => n.Position) .ThenByDescending(n => n.Length) .ToList() ; var stringBuilderPool = StringBuilderPool.Shared; StringBuilder resultBuilder = stringBuilderPool.Rent(); int endPosition = contentLength - 1; int currentPosition = 0; foreach (CssNodeMatch nodeMatch in nodeMatches) { CssNodeType nodeType = nodeMatch.NodeType; int nodePosition = nodeMatch.Position; Match match = nodeMatch.Match; if (nodePosition < currentPosition) { continue; } if (nodeType == CssNodeType.MultilineComment) { int nextPosition = nodePosition + match.Length; ProcessOtherContent(resultBuilder, content, ref currentPosition, nextPosition); } else if (nodeType == CssNodeType.CharsetRule) { ProcessOtherContent(resultBuilder, content, ref currentPosition, nodePosition); string charset = match.Groups["charset"].Value; string charsetRule = match.Value; if (string.IsNullOrWhiteSpace(topCharset)) { topCharset = string.Format(@"@charset ""{0}"";", charset); } currentPosition += charsetRule.Length; } } if (currentPosition > 0 && currentPosition <= endPosition) { ProcessOtherContent(resultBuilder, content, ref currentPosition, endPosition + 1); } string result = resultBuilder.ToString(); stringBuilderPool.Return(resultBuilder); return(result); }
public ClassMatcher(CssNodeType type, string text) : base(type, text) { Text = text?.Substring(1); }
public NthLastOfTypeMatcher(CssNodeType type, string text) : base(type, text) { }
/// <summary> /// Constructs a instance of CSS node match /// </summary> /// <param name="position">Position in the original string where /// the first character of the captured substring was found</param> /// <param name="length">Length of the captured substring</param> /// <param name="nodeType">Type of CSS-node</param> /// <param name="match">Single regular expression match</param> public CssNodeMatch(int position, int length, CssNodeType nodeType, Match match) : base(position, length, match) { NodeType = nodeType; }