Beispiel #1
0
        public Variable(string markup)
        {
            _markup = markup;

            Name    = null;
            Filters = new List <Filter>();

            Match match = MyRegex.Match(markup, string.Format(R.Q(@"\s*({0})(.*)"), Liquid.QuotedAssignFragment));

            if (match.Success)
            {
                Name = match.Groups[1].Value;
                Match filterMatch = MyRegex.Match(match.Groups[2].Value, string.Format(R.Q(@"{0}\s*(.*)"), Liquid.FilterSeparator));
                if (filterMatch.Success)
                {
                    foreach (string f in R.Scan(filterMatch.Value, FilterParser))
                    {
                        Match filterNameMatch = MyRegex.Match(f, R.Q(@"\s*(\w+)"));
                        if (filterNameMatch.Success)
                        {
                            string        filterName = filterNameMatch.Groups[1].Value;
                            List <string> filterArgs = R.Scan(f, string.Format(R.Q(@"(?:{0}|{1})\s*({2})"), Liquid.FilterArgumentSeparator, Liquid.ArgumentSeparator, Liquid.QuotedFragment));
                            Filters.Add(new Filter(filterName, filterArgs.ToArray()));
                        }
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Uses the <tt>Liquid::TemplateParser</tt> regexp to tokenize the passed source
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        internal static List <string> Tokenize(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return(new List <string>());
            }

            // Trim leading whitespace.
            source = MyRegex.Replace(source, string.Format(@"([ \t]+)?({0}|{1})-", Liquid.VariableStart, Liquid.TagStart), "$2");

            // Trim trailing whitespace.
            source = MyRegex.Replace(source, string.Format(@"-({0}|{1})(\n|\r\n|[ \t]+)?", Liquid.VariableEnd, Liquid.TagEnd), "$1");

            List <string> tokens = Regex.Split(source, Liquid.TemplateParser).ToList();

            // Trim any whitespace elements from the end of the array.
            for (int i = tokens.Count - 1; i > 0; --i)
            {
                if (tokens[i] == string.Empty)
                {
                    tokens.RemoveAt(i);
                }
            }

            // Removes the rogue empty element at the beginning of the array
            if (tokens[0] != null && tokens[0] == string.Empty)
            {
                tokens.Shift();
            }

            return(tokens);
        }
Beispiel #3
0
        /// <summary>
        /// Remove all newlines from the string
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string StripNewlines(string input)
        {
            return(input.IsNullOrWhiteSpace()
                                ? input
                : MyRegex.Replace(input, @"(\r?\n)", String.Empty));

            //: Regex.Replace(input, Environment.NewLine, string.Empty);
        }
Beispiel #4
0
        /// <summary>
        /// Replace occurrences of a string with another
        /// </summary>
        /// <param name="input"></param>
        /// <param name="string"></param>
        /// <param name="replacement"></param>
        /// <returns></returns>
        public static string Replace(string input, string @string, string replacement = "")
        {
            if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(@string))
            {
                return(input);
            }

            return(string.IsNullOrEmpty(input)
                                ? input
                                : MyRegex.Replace(input, @string, replacement));
        }
Beispiel #5
0
 /// <summary>
 /// Add <br /> tags in front of all newlines in input string
 /// </summary>
 /// <param name="input"></param>
 /// <returns></returns>
 public static string NewlineToBr(string input)
 {
     return(input.IsNullOrWhiteSpace()
             ? input
             : MyRegex.Replace(input, @"(\r?\n)", "<br />$1"));
 }
Beispiel #6
0
 public static string StripHtml(string input)
 {
     return(input.IsNullOrWhiteSpace()
                         ? input
                         : MyRegex.Replace(input, @"<.*?>", string.Empty));
 }
Beispiel #7
0
        /// <summary>
        /// Resolves namespaced queries gracefully.
        ///
        /// Example
        ///
        /// @context['hash'] = {"name" => 'tobi'}
        /// assert_equal 'tobi', @context['hash.name']
        /// assert_equal 'tobi', @context['hash["name"]']
        /// </summary>
        /// <param name="markup"></param>
        /// <returns></returns>
        private object Variable(string markup)
        {
            List <string> parts           = R.Scan(markup, Liquid.VariableParser);
            Regex         squareBracketed = MyRegex.GetCachedRegex(R.Q(@"^\[(.*)\]$"));

            string firstPart = parts.Shift();
            Match  firstPartSquareBracketedMatch = squareBracketed.Match(firstPart);

            if (firstPartSquareBracketedMatch.Success)
            {
                firstPart = Resolve(firstPartSquareBracketedMatch.Groups[1].Value).ToString();
            }

            object @object;

            if ((@object = FindVariable(firstPart)) != null)
            {
                foreach (string forEachPart in parts)
                {
                    Match partSquareBracketedMatch = squareBracketed.Match(forEachPart);
                    bool  partResolved             = partSquareBracketedMatch.Success;

                    object part = forEachPart;
                    if (partResolved)
                    {
                        part = Resolve(partSquareBracketedMatch.Groups[1].Value);
                    }

                    // If object is a KeyValuePair, we treat it a bit differently - we might be rendering
                    // an included template.
                    if (@object is KeyValuePair <string, object> && ((KeyValuePair <string, object>)@object).Key == (string)part)
                    {
                        object res = ((KeyValuePair <string, object>)@object).Value;
                        @object = Liquidize(res);
                    }
                    // If object is a hash- or array-like object we look for the
                    // presence of the key and if its available we return it
                    else if (IsHashOrArrayLikeObject(@object, part))
                    {
                        // If its a proc we will replace the entry with the proc
                        object res = LookupAndEvaluate(@object, part);
                        @object = Liquidize(res);
                    }
                    // Some special cases. If the part wasn't in square brackets and
                    // no key with the same name was found we interpret following calls
                    // as commands and call them on the current object
                    else if (!partResolved && (@object is IEnumerable) && ((part as string) == "size" || (part as string) == "first" || (part as string) == "last"))
                    {
                        var castCollection = ((IEnumerable)@object).Cast <object>();
                        if ((part as string) == "size")
                        {
                            @object = castCollection.Count();
                        }
                        else if ((part as string) == "first")
                        {
                            @object = castCollection.FirstOrDefault();
                        }
                        else if ((part as string) == "last")
                        {
                            @object = castCollection.LastOrDefault();
                        }
                    }
                    // No key was present with the desired value and it wasn't one of the directly supported
                    // keywords either. The only thing we got left is to return nil
                    else
                    {
                        return(null);
                    }

                    // If we are dealing with a drop here we have to
                    if (@object is IContextAware)
                    {
                        ((IContextAware)@object).Context = this;
                    }
                }
            }

            return(@object);
        }
Beispiel #8
0
        /// <summary>
        /// Look up variable, either resolve directly after considering the name. We can directly handle
        /// Strings, digits, floats and booleans (true,false). If no match is made we lookup the variable in the current scope and
        /// later move up to the parent blocks to see if we can resolve the variable somewhere up the tree.
        /// Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions
        ///
        /// Example:
        ///
        /// products == empty #=> products.empty?
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private object Resolve(string key)
        {
            switch (key)
            {
            case null:
            case "nil":
            case "null":
            case "":
                return(null);

            case "true":
                return(true);

            case "false":
                return(false);

            case "blank":
                return(new Symbol(o => o is IEnumerable && !((IEnumerable)o).Cast <object>().Any()));

            case "empty":
                return(new Symbol(o => o is IEnumerable && !((IEnumerable)o).Cast <object>().Any()));
            }

            // Single quoted strings.
            Match match = MyRegex.Match(key, R.Q(@"^'(.*)'$"));

            if (match.Success)
            {
                return(match.Groups[1].Value);
            }

            // Double quoted strings.
            match = MyRegex.Match(key, R.Q(@"^""(.*)""$"));
            if (match.Success)
            {
                return(match.Groups[1].Value);
            }

            // Integer.
            match = MyRegex.Match(key, R.Q(@"^([+-]?\d+)$"));
            if (match.Success)
            {
                return(Convert.ToInt32(match.Groups[1].Value));
            }

            // Ranges.
            match = MyRegex.Match(key, R.Q(@"^\((\S+)\.\.(\S+)\)$"));
            if (match.Success)
            {
                return(Range.Inclusive(Convert.ToInt32(Resolve(match.Groups[1].Value)),
                                       Convert.ToInt32(Resolve(match.Groups[2].Value))));
            }

            // Floats.
            match = MyRegex.Match(key, R.Q(@"^([+-]?\d[\d\.|\,]+)$"));
            if (match.Success)
            {
                // For cultures with "," as the decimal separator, allow
                // both "," and "." to be used as the separator.
                // First try to parse using current culture.
                float result;
                if (float.TryParse(match.Groups[1].Value, out result))
                {
                    return(result);
                }

                // If that fails, try to parse using invariant culture.
                return(float.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture));
            }

            return(Variable(key));
        }