Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }