コード例 #1
0
ファイル: Mixin.cs プロジェクト: JasonCline/dotless
            public override Node Evaluate(Env env)
            {
                foreach (var frame in env.Frames)
                {
                  NodeList mixins;
                  if ((mixins = frame.Find(Selector, null)).Count == 0)
                continue;

                  var rules = new NodeList();
                  foreach (var node in mixins)
                  {
                if(!(node is Ruleset))
                  continue;

                var ruleset = node as Ruleset;

                if(!ruleset.MatchArguements(Arguments, env))
                  continue;

                if (node is Mixin.Definition)
                {
                  var mixin = node as Mixin.Definition;
                  rules.AddRange(mixin.Evaluate(Arguments, env).Rules);
                }
                else
                {
                  if (ruleset.Rules != null)
                rules.AddRange(ruleset.Rules);
                }
                // todo fix for other Ruleset types?
                  }
                  return rules;
                }
                throw new ParsingException(Selector.ToCSS().Trim() + " is undefined");
            }
コード例 #2
0
ファイル: Parsers.cs プロジェクト: asbjornu/dotless
        //
        // The `primary` rule is the *entry* and *exit* point of the parser.
        // The rules here can appear at any level of the parse tree.
        //
        // The recursive nature of the grammar is an interplay between the `block`
        // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
        // as represented by this simplified grammar:
        //
        //     primary  →  (ruleset | rule)+
        //     ruleset  →  selector+ block
        //     block    →  '{' primary '}'
        //
        // Only at one point is the primary rule not called from the
        // block rule: at the root level.
        //
        public NodeList Primary(Parser parser)
        {
            Node node;
            var root = new NodeList();
            NodeList comments = null;

            GatherComments(parser);

            while (node = MixinDefinition(parser) || Rule(parser) || PullComments() || Ruleset(parser) ||
                          MixinCall(parser) || Directive(parser))
            {
                if (comments = PullComments())
                {
                    root.AddRange(comments);
                }

                comments = node as NodeList;
                if (comments)
                    root.AddRange(comments);
                else
                    root.Add(node);

                GatherComments(parser);
            }
            return root;
        }
コード例 #3
0
ファイル: MixinCall.cs プロジェクト: Tigraine/dotless
        public override Node Evaluate(Env env)
        {
            var found = false;
            var closures = env.FindRulesets(Selector);

            if(closures == null)
                throw new ParsingException(Selector.ToCSS(env).Trim() + " is undefined", Index);

            env.Rule = this;

            var rules = new NodeList();
            foreach (var closure in closures)
            {
                var ruleset = closure.Ruleset;

                if (!ruleset.MatchArguements(Arguments, env))
                    continue;

                found = true;

                if (ruleset is MixinDefinition)
                {
                    try
                    {
                        var mixin = ruleset as MixinDefinition;
                        rules.AddRange(mixin.Evaluate(Arguments, env, closure.Context).Rules);
                    }
                    catch (ParsingException e)
                    {
                        throw new ParsingException(e.Message, e.Index, Index);
                    }
                }
                else
                {
                    if (ruleset.Rules != null)
                    {
                        var nodes = new List<Node>(ruleset.Rules);
                        NodeHelper.ExpandNodes<MixinCall>(env, nodes);

                        rules.AddRange(nodes);
                    }
                }
            }

            env.Rule = null;

            if (!found)
            {
                var message = String.Format("No matching definition was found for `{0}({1})`",
                                            Selector.ToCSS(env).Trim(),
                                            StringExtensions.JoinStrings(Arguments.Select(a => a.ToCSS(env)), ", "));
                throw new ParsingException(message, Index);
            }

            return rules;
        }
コード例 #4
0
    public CartoDefinition(CartoSelector selector, CartoRule[] rules)
    {
      m_rules = new NodeList<CartoRule>();
      m_elements = selector.Elements;
      m_filters = selector.Filters;
      m_rules.AddRange(rules);
      m_zoom = selector.Zoom;
      m_attachment = selector.Attachment ?? "__default__";
      m_ruleIndex = new List<string>();
      for (int i = 0; i < m_rules.Count; i++)
      {
        m_rules[i].Zoom = selector.Zoom;
        m_ruleIndex.Add(m_rules[i].Id);
      }

      m_specificity = selector.Specificity();
    }
コード例 #5
0
ファイル: MixinDefinition.cs プロジェクト: emiaj/dotless
        public Ruleset Evaluate(List<NamedArgument> args, Env env, List<Ruleset> closureContext)
        {
            var frame = EvaluateParams(env, args);

            var frames = new[] { this, frame }.Concat(env.Frames).Concat(closureContext).Reverse();
            var context = env.CreateChildEnv(new Stack<Ruleset>(frames));

            var newRules = new NodeList();

            foreach (var rule in Rules)
            {
                if (rule is MixinDefinition)
                {
                    var mixin = rule as MixinDefinition;
                    var parameters = Enumerable.Concat(mixin.Params, frame.Rules.Cast<Rule>());
                    newRules.Add(new MixinDefinition(mixin.Name, new NodeList<Rule>(parameters), mixin.Rules, mixin.Condition));
                }
                else if (rule is Directive)
                {
                    newRules.Add(rule);
                }
                else if (rule is Ruleset)
                {
                    var ruleset = (rule as Ruleset);

                    context.Frames.Push(ruleset);

                    var rules = new NodeList(NodeHelper.NonDestructiveExpandNodes<MixinCall>(context, ruleset.Rules)
                        .Select(r => r.Evaluate(context)));

                    context.Frames.Pop();

                    newRules.Add(new Ruleset(ruleset.Selectors, rules));
                }
                else if (rule is MixinCall)
                {
                    newRules.AddRange((NodeList)rule.Evaluate(context));
                }
                else
                {
                    newRules.Add(rule.Evaluate(context));
                }
            }

            return new Ruleset(null, newRules);
        }
コード例 #6
0
ファイル: MixinCall.cs プロジェクト: TheCloudlessSky/dotless
        public override Node Evaluate(Env env)
        {
            var found = false;
            var closures = env.FindRulesets(Selector);

            if(closures == null)
                throw new ParsingException(Selector.ToCSS(env).Trim() + " is undefined", Location);

            env.Rule = this;

            var rules = new NodeList();

            if (PreComments)
                rules.AddRange(PreComments);

            foreach (var closure in closures)
            {
                var ruleset = closure.Ruleset;

                var matchType = ruleset.MatchArguments(Arguments, env);

                if (matchType == MixinMatch.ArgumentMismatch)
                    continue;

                found = true;

                if (matchType == MixinMatch.GuardFail)
                    continue;

                if (ruleset is MixinDefinition)
                {
                    try
                    {
                        var mixin = ruleset as MixinDefinition;
                        rules.AddRange(mixin.Evaluate(Arguments, env, closure.Context).Rules);
                    }
                    catch (ParsingException e)
                    {
                        throw new ParsingException(e.Message, e.Location, Location);
                    }
                }
                else
                {
                    if (ruleset.Rules != null)
                    {
                        var nodes = new NodeList(ruleset.Rules);
                        NodeHelper.ExpandNodes<MixinCall>(env, nodes);

                        rules.AddRange(nodes);
                    }
                }
            }
            if (PostComments)
                rules.AddRange(PostComments);

            env.Rule = null;

            if (!found)
            {
                var message = String.Format("No matching definition was found for `{0}({1})`",
                                            Selector.ToCSS(env).Trim(),
                                            Arguments.Select(a => a.Value.ToCSS(env)).JoinStrings(env.Compress ? "," : ", "));
                throw new ParsingException(message, Location);
            }

            if (Important)
            {
                var importantRules = new NodeList();

                foreach (Node node in rules)
                {
                    Rule r = node as Rule;
                    if (r != null)
                    {
                        var valueNode = r.Value;
                        var value = valueNode as Value;
                        value = value != null
                                    ? new Value(value.Values, "!important").ReducedFrom<Value>(value)
                                    : new Value(new NodeList {valueNode}, "!important");

                        importantRules.Add((new Rule(r.Name, value)).ReducedFrom<Rule>(r));
                    }
                    else
                    {
                        importantRules.Add(node);
                    }
                }

                return importantRules;
            }

            return rules;
        }
コード例 #7
0
ファイル: Media.cs プロジェクト: rytmis/dotless
        /// <summary>
        ///  Flattens a list of nodes seperated by comma so that all the conditions are on the bottom.
        ///  e.g.
        ///  (A) and (B) and (C) => A and B and C
        ///  (A, B) and (D) and (C) => A and D and C, B and D and C
        ///  (A) and (B) and (C, D) => A and B and C, A and B and D
        /// 
        ///  It does this by generating a list of permutations for the last n-1 then n-2
        ///  and with each call it multiplies out the OR'd elements
        /// </summary>
        private NodeList Permute(NodeList<NodeList> arr)
        {
            // in simple cases return
            if (arr.Count == 0)
                return new NodeList();

            if (arr.Count == 1)
            {
                return arr[0];
            }

            NodeList returner = new NodeList();

            // run permute on the next n-1
            NodeList<NodeList> sliced = new NodeList<NodeList>(arr.Skip(1));
            NodeList rest = Permute(sliced);

            //now multiply
            for (int i = 0; i < rest.Count; i++)
            {
                NodeList inner = arr[0];
                for (int j = 0; j < inner.Count; j++)
                {
                    NodeList newl = new NodeList();
                    newl.Add(inner[j]);

                    NodeList addition = rest[i] as NodeList;
                    if (addition)
                    {
                        newl.AddRange(addition);
                    }
                    else
                    {
                        newl.Add(rest[i]);
                    }

                    //add an expression so it seperated by spaces
                    returner.Add(new Expression(newl));
                }
            }

            return returner;
        }
コード例 #8
0
ファイル: MixinDefinition.cs プロジェクト: bgrins/dotless
        public Ruleset Evaluate(List<NamedArgument> args, Env env, List<Ruleset> closureContext)
        {
            //            if (args != null && args.Any())
            //                Guard.ExpectMaxArguments(Params.Count, args.Count, String.Format("'{0}'", Name), Index);

            var arguments = new Dictionary<string, Node>();
            args = args ?? new List<NamedArgument>();

            var hasNamedArgs = false;
            foreach (var arg in args)
            {
                if (!string.IsNullOrEmpty(arg.Name))
                {
                    hasNamedArgs = true;

                    arguments[arg.Name] = new Rule(arg.Name, arg.Value.Evaluate(env)) { Index = arg.Value.Index };
                }
                else if (hasNamedArgs)
                    throw new ParsingException("Positional arguments must appear before all named arguments.", arg.Value.Index);
            }

            for (var i = 0; i < Params.Count; i++)
            {
                if (String.IsNullOrEmpty(Params[i].Name))
                    continue;

                if (arguments.ContainsKey(Params[i].Name))
                    continue;

                Node val;
                if (i < args.Count && string.IsNullOrEmpty(args[i].Name))
                    val = args[i].Value;
                else
                    val = Params[i].Value;

                if (val)
                    arguments[Params[i].Name] = new Rule(Params[i].Name, val.Evaluate(env)) {Index = val.Index};
                else
                    throw new ParsingException(
                        String.Format("wrong number of arguments for {0} ({1} for {2})", Name,
                                      args != null ? args.Count : 0, _arity), Index);
            }

            var _arguments = new List<Node>();

            for(var i = 0; i < Math.Max(Params.Count, args.Count); i++)
            {
              _arguments.Add(i < args.Count ? args[i].Value : Params[i].Value);
            }

            var frame = new Ruleset(null, new NodeList());

            frame.Rules.Insert(0, new Rule("@arguments", new Expression(_arguments.Where(a => a != null)).Evaluate(env)));

            foreach (var arg in arguments)
            {
                frame.Rules.Add(arg.Value);
            }

            var frames = new[] { this, frame }.Concat(env.Frames).Concat(closureContext).Reverse();
            var context = new Env {Frames = new Stack<Ruleset>(frames)};

            var newRules = new NodeList();

            foreach (var rule in Rules)
            {
                if (rule is MixinDefinition)
                {
                    var mixin = rule as MixinDefinition;
                    var parameters = Enumerable.Concat(mixin.Params, frame.Rules.Cast<Rule>());
                    newRules.Add(new MixinDefinition(mixin.Name, new NodeList<Rule>(parameters), mixin.Rules));
                }
                else if (rule is Ruleset)
                {
                    var ruleset = (rule as Ruleset);

                    context.Frames.Push(ruleset);

                    var rules = new NodeList(NodeHelper.NonDestructiveExpandNodes<MixinCall>(context, ruleset.Rules)
                        .Select(r => r.Evaluate(context)));

                    context.Frames.Pop();

                    newRules.Add(new Ruleset(ruleset.Selectors, rules));
                }
                else if (rule is MixinCall)
                {
                    newRules.AddRange((NodeList) rule.Evaluate(context));
                }
                else
                {
                    newRules.Add(rule.Evaluate(context));
                }
            }

            return new Ruleset(null, newRules);
        }
コード例 #9
0
ファイル: MixinCall.cs プロジェクト: Ralphvanderneut/dotless
        public override Node Evaluate(Env env)
        {
            var closures = env.FindRulesets(Selector);
            if (closures == null)
                throw new ParsingException(Selector.ToCSS(env).Trim() + " is undefined", Location);

            env.Rule = this;

            var rules = new NodeList();

            if (PreComments)
                rules.AddRange(PreComments);

            var rulesetList = closures.ToList();

            // To address bug https://github.com/dotless/dotless/issues/136, where a mixin and ruleset selector may have the same name, we
            // need to favour matching a MixinDefinition with the required Selector and only fall back to considering other Ruleset types
            // if no match is found.
            // However, in order to support having a regular ruleset with the same name as a parameterized
            // mixin (see https://github.com/dotless/dotless/issues/387), we need to take argument counts into account, so we make the
            // decision after evaluating for argument match.

            var mixins = rulesetList.Where(c => c.Ruleset is MixinDefinition).ToList();

            var defaults = new List<Closure>();

            bool foundMatches = false, foundExactMatches = false, foundDefaultMatches = false;
            foreach (var closure in mixins)
            {
                var ruleset = (MixinDefinition)closure.Ruleset;
                var matchType = ruleset.MatchArguments(Arguments, env);
                if (matchType == MixinMatch.ArgumentMismatch)
                {
                    continue;
                }

                if (matchType == MixinMatch.Default) {
                    defaults.Add(closure);
                    foundDefaultMatches = true;

                    continue;
                }

                foundMatches = true;

                if (matchType == MixinMatch.GuardFail)
                {
                    continue;
                }

                foundExactMatches = true;

                try
                {
                    var closureEnvironment = env.CreateChildEnvWithClosure(closure);
                    rules.AddRange(ruleset.Evaluate(Arguments, closureEnvironment).Rules);
                }
                catch (ParsingException e)
                {
                    throw new ParsingException(e.Message, e.Location, Location);
                }
            }

            if (!foundExactMatches && foundDefaultMatches) {
                foreach (var closure in defaults) {
                    try {
                        var closureEnvironment = env.CreateChildEnvWithClosure(closure);
                        var ruleset = (MixinDefinition) closure.Ruleset;
                        rules.AddRange(ruleset.Evaluate(Arguments, closureEnvironment).Rules);
                    } catch (ParsingException e) {
                        throw new ParsingException(e.Message, e.Location, Location);
                    }
                }
                foundMatches = true;
            }

            if (!foundMatches)
            {
                var regularRulesets = rulesetList.Except(mixins);

                foreach (var closure in regularRulesets)
                {
                    if (closure.Ruleset.Rules != null) {
                        var nodes = (NodeList)closure.Ruleset.Rules.Clone();
                        NodeHelper.ExpandNodes<MixinCall>(env, nodes);

                        rules.AddRange(nodes);
                    }

                    foundMatches = true;
                }
            }

            if (PostComments)
                rules.AddRange(PostComments);

            env.Rule = null;

            if (!foundMatches)
            {
                var message = String.Format("No matching definition was found for `{0}({1})`",
                                            Selector.ToCSS(env).Trim(),
                                            Arguments.Select(a => a.Value.ToCSS(env)).JoinStrings(env.Compress ? "," : ", "));
                throw new ParsingException(message, Location);
            }

            rules.Accept(new ReferenceVisitor(IsReference));

            if (Important)
            {
                return MakeRulesImportant(rules);
            }

            return rules;
        }
コード例 #10
0
ファイル: MixinDefinition.cs プロジェクト: helephant/dotless
        public Ruleset Evaluate(List<NamedArgument> args, Env env, List<Ruleset> closureContext)
        {
            var frame = EvaluateParams(env, args);

            var frames = new[] { this, frame }.Concat(env.Frames).Concat(closureContext).Reverse();
            var context = env.CreateChildEnv(new Stack<Ruleset>(frames));

            var newRules = new NodeList();

            foreach (var rule in Rules)
            {
                if (rule is MixinDefinition)
                {
                    var mixin = rule as MixinDefinition;
                    var parameters = Enumerable.Concat(mixin.Params, frame.Rules.Cast<Rule>());
                    newRules.Add(new MixinDefinition(mixin.Name, new NodeList<Rule>(parameters), mixin.Rules, mixin.Condition, mixin.Variadic));
                }
                else if (rule is Import)
                {
                    var potentiolNodeList = rule.Evaluate(context);
                    var nodeList = potentiolNodeList as NodeList;
                    if (nodeList != null)
                    {
                        newRules.AddRange(nodeList);
                    }
                    else
                    {
                        newRules.Add(potentiolNodeList);
                    }
                }
                else if (rule is Directive || rule is Media)
                {
                    newRules.Add(rule.Evaluate(context));
                }
                else if (rule is Ruleset)
                {
                    var ruleset = (rule as Ruleset);

                    context.Frames.Push(ruleset);

                    newRules.Add(ruleset.Evaluate(context));

                    context.Frames.Pop();
                }
                else if (rule is MixinCall)
                {
                    newRules.AddRange((NodeList)rule.Evaluate(context));
                }
                else
                {
                    newRules.Add(rule.Evaluate(context));
                }
            }

            return new Ruleset(null, newRules);
        }
コード例 #11
0
ファイル: Ruleset.cs プロジェクト: JasonCline/dotless
        public NodeList Find(Selector selector, Ruleset self)
        {
            self = self ?? this;
              var rules = new NodeList();
              var key = selector.ToCSS();

              if (_lookups.ContainsKey(key))
            return _lookups[key];

              foreach (var rule in Rulesets().Where(rule => rule != self))
              {
            if (rule.Selectors && rule.Selectors.Any(selector.Match))
            {
              if (selector.Elements.Count > 1)
              {
            var remainingSelectors = new Selector(new NodeList<Element>(selector.Elements.Skip(1)));
            rules.AddRange(rule.Find(remainingSelectors, self));
              }
              else
            rules.Add(rule);
            }
              }
              return _lookups[key] = rules;
        }
コード例 #12
0
ファイル: MixinCall.cs プロジェクト: ikvm/dotless
        public override Node Evaluate(Env env)
        {
            var found    = false;
            var closures = env.FindRulesets(Selector);

            if (closures == null)
            {
                throw new ParsingException(Selector.ToCSS(env).Trim() + " is undefined", Index);
            }

            env.Rule = this;

            var rules = new NodeList();

            if (PreComments)
            {
                rules.Add(PreComments);
            }
            foreach (var closure in closures)
            {
                var ruleset = closure.Ruleset;

                if (!ruleset.MatchArguments(Arguments, env))
                {
                    continue;
                }

                found = true;

                if (ruleset is MixinDefinition)
                {
                    try
                    {
                        var mixin = ruleset as MixinDefinition;
                        rules.AddRange(mixin.Evaluate(Arguments, env, closure.Context).Rules);
                    }
                    catch (ParsingException e)
                    {
                        throw new ParsingException(e.Message, e.Index, Index);
                    }
                }
                else
                {
                    if (ruleset.Rules != null)
                    {
                        var nodes = new NodeList(ruleset.Rules);
                        NodeHelper.ExpandNodes <MixinCall>(env, nodes);

                        rules.AddRange(nodes);
                    }
                }
            }
            if (PostComments)
            {
                rules.Add(PostComments);
            }

            env.Rule = null;

            if (!found)
            {
                var message = String.Format("No matching definition was found for `{0}({1})`",
                                            Selector.ToCSS(env).Trim(),
                                            StringExtensions.JoinStrings(Arguments.Select(a => a.Value.ToCSS(env)), ", "));
                throw new ParsingException(message, Index);
            }

            return(rules);
        }