示例#1
0
        public void BlockHelperWithBlockParams()
        {
            var handlebars = Handlebars.Create();

            handlebars.RegisterHelper("myHelper", (writer, options, context, args) =>
            {
                using var frame       = options.CreateFrame();
                var blockParamsValues = new BlockParamsValues(frame, options.BlockParams);
                blockParamsValues.CreateProperty(0, out var _0);

                for (var index = 0; index < args.Length; index++)
                {
                    var arg = args[index];
                    blockParamsValues[_0] = index;
                    frame.Value           = arg;
                    options.Template(writer, frame);
                }
            });

            var source = "Here are some things: {{#myHelper 'foo' 'bar' as |counter|}}{{counter}}:{{this}}\n{{/myHelper}}";

            var template = handlebars.Compile(source);

            var output = template(new { });

            var expected = "Here are some things: 0:foo\n1:bar\n";

            Assert.Equal(expected, output);
        }
        private static void IterateObjectWithStaticProperties(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            ObjectDescriptor descriptor,
            object target,
            IList <ChainSegment> properties,
            Type targetType,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new ObjectIteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var count    = properties.Count;
            var accessor = new MemberAccessor(target, descriptor);

            var iterationIndex = 0;
            var lastIndex      = count - 1;

            object       iteratorValue;
            ChainSegment iteratorKey;

            for (; iterationIndex < count; iterationIndex++)
            {
                iteratorKey = properties[iterationIndex];

                iterator.Index = iterationIndex;
                iterator.Key   = iteratorKey;
                if (iterationIndex == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (iterationIndex == lastIndex)
                {
                    iterator.Last = BoxedValues.True;
                }

                iteratorValue      = accessor[iteratorKey];
                iterator.Value     = iteratorValue;
                innerContext.Value = iteratorValue;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = iteratorKey;

                template(writer, innerContext);
            }

            if (iterationIndex == 0)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        private static void IterateObject(
            BindingContext context,
            EncodedTextWriter writer,
            ObjectDescriptor descriptor,
            ChainSegment[] blockParamsVariables,
            object target,
            IEnumerable properties,
            Type targetType,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new ObjectIteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var accessor   = new MemberAccessor(target, descriptor);
            var enumerable = new ExtendedEnumerator <object>(properties.GetEnumerator());
            var enumerated = false;

            object       iteratorValue;
            ChainSegment iteratorKey;

            while (enumerable.MoveNext())
            {
                enumerated = true;
                var enumerableValue = enumerable.Current;
                iteratorKey = ChainSegment.Create(enumerableValue.Value);

                iterator.Key   = iteratorKey;
                iterator.Index = enumerableValue.Index;
                if (enumerableValue.Index == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (enumerableValue.IsLast)
                {
                    iterator.Last = BoxedValues.True;
                }

                iteratorValue      = accessor[iteratorKey];
                iterator.Value     = iteratorValue;
                innerContext.Value = iteratorValue;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = iteratorKey;

                template(writer, innerContext);
            }

            if (!enumerated)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        private static void IterateEnumerable(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            IEnumerable target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new IteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var enumerator = new ExtendedEnumerator <object>(target.GetEnumerator());
            var enumerated = false;

            object boxedIndex;
            object iteratorValue;

            while (enumerator.MoveNext())
            {
                enumerated = true;
                var enumerableValue = enumerator.Current;

                if (enumerableValue.Index == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (enumerableValue.IsLast)
                {
                    iterator.Last = BoxedValues.True;
                }

                boxedIndex     = enumerableValue.Index;
                iteratorValue  = enumerableValue.Value;
                iterator.Value = iteratorValue;
                iterator.Index = boxedIndex;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = boxedIndex;

                innerContext.Value = iteratorValue;

                template(writer, innerContext);
            }

            if (!enumerated)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        private static void IterateList(
            BindingContext context,
            EncodedTextWriter writer,
            ChainSegment[] blockParamsVariables,
            IList target,
            TemplateDelegate template,
            TemplateDelegate ifEmpty)
        {
            using var innerContext = context.CreateFrame();
            var iterator    = new IteratorValues(innerContext);
            var blockParams = new BlockParamsValues(innerContext, blockParamsVariables);

            blockParams.CreateProperty(0, out var _0);
            blockParams.CreateProperty(1, out var _1);

            var count = target.Count;

            object boxedIndex;
            object iteratorValue;

            var iterationIndex = 0;
            var lastIndex      = count - 1;

            for (; iterationIndex < count; iterationIndex++)
            {
                iteratorValue = target[iterationIndex];

                iterator.Value = iteratorValue;
                if (iterationIndex == 1)
                {
                    iterator.First = BoxedValues.False;
                }
                if (iterationIndex == lastIndex)
                {
                    iterator.Last = BoxedValues.True;
                }

                boxedIndex     = iterationIndex;
                iterator.Index = boxedIndex;

                blockParams[_0] = iteratorValue;
                blockParams[_1] = boxedIndex;

                innerContext.Value = iteratorValue;

                template(writer, innerContext);
            }

            if (iterationIndex == 0)
            {
                innerContext.Value = context.Value;
                ifEmpty(writer, innerContext);
            }
        }
        public override void Invoke(TextWriter output, HelperOptions options, object context, params object[] arguments)
        {
            if (arguments.Length != 1)
            {
                throw new HandlebarsException("{{with}} helper must have exactly one argument");
            }

            if (HandlebarsUtils.IsTruthyOrNonEmpty(arguments[0]))
            {
                using var frame = options.CreateFrame(arguments[0]);
                var blockParamsValues = new BlockParamsValues(frame, options.BlockParams);

                blockParamsValues.CreateProperty(0, out var _0);

                blockParamsValues[_0] = arguments[0];

                options.Template(output, frame);
            }
            else
            {
                options.Inverse(output, context);
            }
        }