public List <Closure> Find(Env env, Selector selector, Ruleset self) { self = self ?? this; var rules = new List <Closure>(); var key = selector.ToCSS(env); if (_lookups.ContainsKey(key)) { return(_lookups[key]); } var validRulesets = Rulesets().Where(rule => { if (rule != self) { return(true); } MixinDefinition mixinRule = rule as MixinDefinition; if (mixinRule != null) { return(mixinRule.Condition != null); } return(false); }); foreach (var rule in validRulesets) { if (rule.Selectors && rule.Selectors.Any(selector.Match)) { if (selector.Elements.Count > 1) { var remainingSelectors = new Selector(new NodeList <Element>(selector.Elements.Skip(1))); var closures = rule.Find(env, remainingSelectors, self); foreach (var closure in closures) { closure.Context.Insert(0, rule); } rules.AddRange(closures); } else { rules.Add(new Closure { Ruleset = rule, Context = new List <Ruleset> { rule } }); } } } return(_lookups[key] = rules); }
public List <Closure> Find <TRuleset>(Env env, Selector selector, Ruleset self) where TRuleset : Ruleset { self = self ?? this; var rules = new List <Closure>(); var key = typeof(TRuleset).ToString() + ":" + selector.ToCSS(env); if (_lookups.ContainsKey(key)) { return(_lookups[key]); } var validRulesets = Rulesets().Where(rule => { if (!typeof(TRuleset).IsAssignableFrom(rule.GetType())) { return(false); } if (rule != self) { return(true); } MixinDefinition mixinRule = rule as MixinDefinition; if (mixinRule != null) { return(mixinRule.Condition != null); } return(false); }); foreach (var rule in validRulesets) { if (rule.Selectors && rule.Selectors.Any(selector.Match)) { if ((selector.Elements.Count == 1) || rule.Selectors.Any(s => s.ToCSS(new Env()) == selector.ToCSS(new Env()))) { rules.Add(new Closure { Ruleset = rule, Context = new List <Ruleset> { rule } }); } else if (selector.Elements.Count > 1) { var remainingSelectors = new Selector(new NodeList <Element>(selector.Elements.Skip(1))); var closures = rule.Find <Ruleset>(env, remainingSelectors, self); foreach (var closure in closures) { closure.Context.Insert(0, rule); } rules.AddRange(closures); } } } return(_lookups[key] = rules); }
private IEnumerable <Closure> FindInternal(Env env, Selector selector, Ruleset self, Context context) { if (!selector.Elements.Any()) { return(Enumerable.Empty <Closure>()); } string selectorCss = selector.ToCSS(env); var key = selectorCss; if (_lookups.ContainsKey(key)) { return(_lookups[key]); } self = self ?? this; var rules = new List <Closure>(); var bestMatch = context.Select(selectors => new Selector(selectors.SelectMany(s => s.Elements))) .Where(m => m.Elements.IsSubsequenceOf(selector.Elements, ElementValuesEqual)) .OrderByDescending(m => m.Elements.Count) .FirstOrDefault(); if (bestMatch != null && bestMatch.Elements.Count == selector.Elements.Count) { // exact match, good to go rules.Add(new Closure { Context = new List <Ruleset> { this }, Ruleset = this }); } var validRulesets = Rulesets().Where(rule => { if (rule != self) { return(true); } MixinDefinition mixinRule = rule as MixinDefinition; if (mixinRule != null) { return(mixinRule.Condition != null); } return(false); }); foreach (var rule in validRulesets) { if (rule.Selectors == null) { continue; } var childContext = new Context(); childContext.AppendSelectors(context, rule.Selectors); var closures = rule.FindInternal(env, selector, self, childContext); foreach (var closure in closures) { closure.Context.Insert(0, this); rules.Add(closure); } } return(_lookups[key] = rules); }