Ejemplo n.º 1
0
        /// <summary>
        /// Writes an object value to the current <see cref="Output"/>.
        /// </summary>
        /// <param name="span">The span of the object to render.</param>
        /// <param name="textAsObject">The text as object.</param>
        public void Write(SourceSpan span, object textAsObject)
        {
            if (textAsObject == null)
            {
                return;
            }
            var text = ScriptValueConverter.ToString(span, textAsObject);

            Write(text);
        }
Ejemplo n.º 2
0
        private static object Map(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count != 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for map. Expecting at 2 parameters: <property> <array>");
            }

            var member = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            var target = parameters[1];

            return(Map(context, target, member));
        }
Ejemplo n.º 3
0
        public override void Evaluate(TemplateContext context)
        {
            var conditionValue = ScriptValueConverter.ToBool(context.Evaluate(Condition));

            if (conditionValue)
            {
                Then?.Evaluate(context);
            }
            else
            {
                base.Evaluate(context);
            }
        }
Ejemplo n.º 4
0
        private static object Round(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 1 || parameters.Count > 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for math.round. Expecting at least 1 parameter <precision>? <value>");
            }

            var value     = ScriptValueConverter.ToDouble(callerContext.Span, parameters[parameters.Count - 1]);
            int precision = 0;

            if (parameters.Count == 2)
            {
                precision = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            }

            return(Round(precision, value));
        }
Ejemplo n.º 5
0
        private static object Sort(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 1 || parameters.Count > 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for sort. Expecting at least 1 parameter <property>? <array>");
            }

            var    target = parameters[parameters.Count - 1];
            string member = null;

            if (parameters.Count == 2)
            {
                member = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            }

            return(Sort(context, target, member));
        }
Ejemplo n.º 6
0
        public static string Join(string delimiter, IEnumerable enumerable)
        {
            var  text       = new StringBuilder();
            bool afterFirst = false;

            foreach (var obj in enumerable)
            {
                if (afterFirst)
                {
                    text.Append(delimiter);
                }
                // TODO: We need to convert to a string but we don't have a span!
                text.Append(ScriptValueConverter.ToString(new SourceSpan("unknown", new TextPosition(), new TextPosition()), obj));
                afterFirst = true;
            }
            return(text.ToString());
        }
Ejemplo n.º 7
0
        private static object Slice(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 2 || parameters.Count > 3)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for slice. Expecting at least 2 parameters <start> <length>? <text>");
            }

            var text   = ScriptValueConverter.ToString(callerContext.Span, parameters[parameters.Count - 1]);
            var start  = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            var length = -1;

            if (parameters.Count == 3)
            {
                length = ScriptValueConverter.ToInt(callerContext.Span, parameters[1]);
            }

            return(Slice(text, start, length));
        }
Ejemplo n.º 8
0
        protected override void EvaluateImpl(TemplateContext context)
        {
            var index = 0;

            while (context.StepLoop())
            {
                var conditionResult = ScriptValueConverter.ToBool(context.Evaluate(Condition));
                if (!conditionResult)
                {
                    break;
                }

                if (!Loop(context, index++))
                {
                    break;
                }
            }
            ;
        }
Ejemplo n.º 9
0
 public override string ToString()
 {
     return(Value == null ? string.Empty : ScriptValueConverter.ToString(Span, Value));
 }
Ejemplo n.º 10
0
        private object GetOrSetValue(ScriptExpression targetExpression, object valueToSet, bool setter, int level)
        {
            object value = null;

            var nextVariable = targetExpression as ScriptVariable;

            if (nextVariable != null)
            {
                if (setter)
                {
                    SetValue(nextVariable, valueToSet, false);
                }
                else
                {
                    value = GetValueInternal(nextVariable);
                }
            }
            else
            {
                var nextDot = targetExpression as ScriptMemberExpression;
                if (nextDot != null)
                {
                    var targetObject = GetOrSetValue(nextDot.Target, valueToSet, false, level + 1);

                    if (targetObject == null)
                    {
                        throw new ScriptRuntimeException(nextDot.Span, $"Object [{nextDot.Target}] is null. Cannot access member: {nextDot}"); // unit test: 131-member-accessor-error1.txt
                    }

                    if (targetObject is string || targetObject.GetType().GetTypeInfo().IsPrimitive)
                    {
                        throw new ScriptRuntimeException(nextDot.Span, $"Cannot get or set a member on the primitive [{targetObject}/{targetObject.GetType()}] when accessing member: {nextDot}"); // unit test: 132-member-accessor-error2.txt
                    }

                    var accessor = GetMemberAccessor(targetObject);

                    var memberName = nextDot.Member.Name;

                    if (setter)
                    {
                        if (!accessor.TrySetValue(targetObject, memberName, valueToSet))
                        {
                            throw new ScriptRuntimeException(nextDot.Member.Span, $"Cannot set a value for the readonly member: {nextDot}"); // unit test: 132-member-accessor-error3.txt
                        }
                    }
                    else
                    {
                        value = accessor.GetValue(targetObject, memberName);
                    }
                }
                else
                {
                    var nextIndexer = targetExpression as ScriptIndexerExpression;
                    if (nextIndexer != null)
                    {
                        var targetObject = GetOrSetValue(nextIndexer.Target, valueToSet, false, level + 1);
                        if (targetObject == null)
                        {
                            throw new ScriptRuntimeException(nextIndexer.Target.Span, $"Object [{nextIndexer.Target}] is null. Cannot access indexer: {nextIndexer}"); // unit test: 130-indexer-accessor-error1.txt
                        }
                        else
                        {
                            var index = this.Evaluate(nextIndexer.Index);
                            if (index == null)
                            {
                                throw new ScriptRuntimeException(nextIndexer.Index.Span, $"Cannot access target [{nextIndexer.Target}] with a null indexer: {nextIndexer}"); // unit test: 130-indexer-accessor-error2.txt
                            }
                            else
                            {
                                if (targetObject is IDictionary || targetObject is ScriptObject)
                                {
                                    var accessor      = GetMemberAccessor(targetObject);
                                    var indexAsString = ScriptValueConverter.ToString(nextIndexer.Index.Span, index);

                                    if (setter)
                                    {
                                        if (!accessor.TrySetValue(targetObject, indexAsString, valueToSet))
                                        {
                                            throw new ScriptRuntimeException(nextIndexer.Index.Span, $"Cannot set a value for the readonly member [{indexAsString}] in the indexer: {nextIndexer.Target}['{indexAsString}']"); // unit test: 130-indexer-accessor-error3.txt
                                        }
                                    }
                                    else
                                    {
                                        value = accessor.GetValue(targetObject, indexAsString);
                                    }
                                }
                                else
                                {
                                    var accessor = GetListAccessor(targetObject);
                                    if (accessor == null)
                                    {
                                        throw new ScriptRuntimeException(nextIndexer.Target.Span, $"Expecting a list. Invalid value [{targetObject}/{targetObject?.GetType().Name}] for the target [{nextIndexer.Target}] for the indexer: {nextIndexer}"); // unit test: 130-indexer-accessor-error4.txt
                                    }
                                    else
                                    {
                                        int i = ScriptValueConverter.ToInt(nextIndexer.Index.Span, index);

                                        // Allow negative index from the end of the array
                                        if (i < 0)
                                        {
                                            i = accessor.GetLength(targetObject) + i;
                                        }

                                        if (i >= 0)
                                        {
                                            if (setter)
                                            {
                                                accessor.SetValue(targetObject, i, valueToSet);
                                            }
                                            else
                                            {
                                                value = accessor.GetValue(targetObject, i);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else if (!setter)
                    {
                        targetExpression.Evaluate(this);
                        value       = this.Result;
                        this.Result = null;
                    }
                    else
                    {
                        throw new ScriptRuntimeException(targetExpression.Span, $"Unsupported expression for target for assignment: {targetExpression} = ..."); // unit test: 105-assign-error1.txt
                    }
                }
            }

            // If the variable being returned is a function, we need to evaluate it
            // If function call is disabled, it will be only when returning the final object (level 0 of recursion)
            if ((!isFunctionCallDisabled || level > 0) && ScriptFunctionCall.IsFunction(value))
            {
                value = ScriptFunctionCall.Call(this, targetExpression, value);
            }

            return(value);
        }
Ejemplo n.º 11
0
        public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement)
        {
            if (parameters.Count == 0)
            {
                throw new ScriptRuntimeException(callerContext.Span, "Expecting at least the name of the template to include for the <include> function");
            }

            string templateName = null;

            try
            {
                templateName = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            }
            catch (Exception ex)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception while converting first parameter for <include> function. Expecting a string", ex);
            }

            // If template name is empty, throw an exception
            if (templateName == null || string.IsNullOrEmpty(templateName = templateName.Trim()))
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Include template name cannot be null or empty");
            }

            // Compute a new parameters for the include
            var newParameters = new ScriptArray(parameters.Count - 1);

            for (int i = 1; i < parameters.Count; i++)
            {
                newParameters[i] = parameters[i];
            }

            context.SetValue(ScriptVariable.Arguments, newParameters, true);

            Template template;

            if (!context.CachedTemplates.TryGetValue(templateName, out template))
            {
                if (context.TemplateLoader == null)
                {
                    throw new ScriptRuntimeException(callerContext.Span,
                                                     $"Unable to include <{templateName}>. No TemplateLoader registered in TemplateContext.Options.TemplateLoader");
                }

                string templateFilePath;

                var templateText = context.TemplateLoader.Load(context, callerContext.Span, templateName, out templateFilePath);

                if (templateText == null)
                {
                    throw new ScriptRuntimeException(callerContext.Span, $"The result of including <{templateName}> cannot be null");
                }

                // IF template file path is not defined, we use the template name instead
                templateFilePath = templateFilePath ?? templateName;

                // Clone parser options
                var parserOptions = context.TemplateLoaderParserOptions.Clone();

                // Parse include in default modes (while top page can be using front matter)
                parserOptions.Mode = parserOptions.Mode == ScriptMode.ScriptOnly
                    ? ScriptMode.ScriptOnly
                    : ScriptMode.Default;

                template = Template.Parse(templateText, templateFilePath, parserOptions);

                // If the template has any errors, throw an exception
                if (template.HasErrors)
                {
                    throw new ScriptParserRuntimeException(callerContext.Span, $"Error while parsing template <{templateName}> from [{templateFilePath}]", template.Messages);
                }

                context.CachedTemplates.Add(templateName, template);
            }

            // Query the pending includes stored in the context
            HashSet <string> pendingIncludes;
            object           pendingIncludesObject;

            if (!context.Tags.TryGetValue(typeof(IncludeFunction), out pendingIncludesObject))
            {
                pendingIncludesObject = pendingIncludes = new HashSet <string>();
                context.Tags[typeof(IncludeFunction)] = pendingIncludesObject;
            }
            else
            {
                pendingIncludes = (HashSet <string>)pendingIncludesObject;
            }

            // Make sure that we cannot recursively include a template
            if (pendingIncludes.Contains(templateName))
            {
                throw new ScriptRuntimeException(callerContext.Span, $"The include [{templateName}] cannot be used recursively");
            }
            pendingIncludes.Add(templateName);

            context.PushOutput();
            object result = null;

            try
            {
                template.Render(context);
            }
            finally
            {
                result = context.PopOutput();
                pendingIncludes.Remove(templateName);
            }

            return(result);
        }