Esempio n. 1
0
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer)
		{
			if (context.Service == null)
			{
				// There is nothing we can do, no service has been assigned.
				return;
			}

			var options = new HelperOptions()
			{
				Arguments = arguments,
				Parameters = maps,
				RenderContext = context
			};

			if (block.Type == BlockType.Tag)
			{
				var children = block.Children.ToList();
				children.RemoveAt(0);
				children.RemoveAt(children.Count - 1);

				options.Render = (data) => RenderHelperChildren(children, context, data);
			}

			string result = context.Service.RunHelper(block.Name, options);

			Write(context, writer, new SafeString(result));
		}
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer)
		{
			var enumerable = arguments[0];
			if (!(enumerable is IEnumerable))
			{
				enumerable = new object[] { enumerable };
			}

			var children = block.Children.ToList();
			children.RemoveAt(0);
			children.RemoveAt(children.Count - 1);

			var elseChildren = new List<SyntaxTreeNode>();

			// Determine if there is an alternate {{else}} block which denotes content to display when there are no items.
			var elseNode = children.Find(n => n.IsBlock && (((Block)n).Name == "else" || ((Block)n).Name == "^"));
			if (elseNode != null)
			{
				int elseIndex = children.IndexOf(elseNode);
				elseChildren = children.Skip(elseIndex + 1).ToList();
				children = children.Take(elseIndex).ToList();
			}

			RenderEnumerable((IEnumerable)enumerable, context, children, elseChildren);
		}
Esempio n. 3
0
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer)
		{
			if (context.Service == null)
			{
				// No service, can't do anything.
				return;
			}

			var span = block.Children.FirstOrDefault(c => !c.IsBlock && ((Span)c).Kind == SpanKind.Expression) as Span;
			if (span == null)
			{
				// Malformed tag?
				return;
			}

			string name = span.Content;
			object model = arguments.FirstOrDefault();

			if (model != null)
			{
				using (var scope = context.BeginScope(model))
				{
					Write(scope.ScopeContext, writer, new SafeString(context.Service.RunPartial(name, scope.ScopeContext)));
				}
			}
			else
			{
				Write(context, writer, new SafeString(context.Service.RunPartial(name, context)));
			}
		}
Esempio n. 4
0
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer)
		{
			var children = block.Children.ToList();
			children.RemoveAt(0);
			children.RemoveAt(children.Count - 1);

			var elseChildren = new List<SyntaxTreeNode>();

			// Determine if there is an alternate {{else}} block which denotes content to display when predicate is false.
			var elseNode = children.Find(n => n.IsBlock && (((Block)n).Name == "else" || ((Block)n).Name == "^"));
			if (elseNode != null)
			{
				int elseIndex = children.IndexOf(elseNode);
				elseChildren = children.Skip(elseIndex + 1).ToList();
				children = children.Take(elseIndex).ToList();
			}

			if (!IsTruthy(arguments[0]))
			{
				RenderChildren(children, context);
			}
			else if (elseChildren.Count > 0)
			{
				RenderChildren(elseChildren, context);
			}
		}
Esempio n. 5
0
		/// <summary>
		/// Initialises a new instance of <see cref="BlockBuilder"/>
		/// </summary>
		/// <param name="original">The original block.</param>
		public BlockBuilder(Block original)
		{
			Type = original.Type;
			Name = original.Name;
			Descriptor = original.Descriptor;
			Children = new List<SyntaxTreeNode>(original.Children);
		}
Esempio n. 6
0
		/// <inheritdoc />
		public virtual void VisitBlock(Block block)
		{
			VisitStartBlock(block);
			foreach (var node in block.Children)
			{
				node.Accept(this);
			}
			VisitEndBlock(block);
		}
Esempio n. 7
0
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer)
		{
			string name = block.Name;

			var children = block.Children.ToList();

			// Get the TagElement block.
			var tagElement = (Block)children[0];
			// Determine if the block prefix symbol (either # or ^) is a caret.
			bool isNegatedSection = tagElement.Children.Cast<Span>().Where(s => s.Kind == SpanKind.MetaCode).ToArray()[1].Content == "^";

			children.RemoveAt(0);
			children.RemoveAt(children.Count - 1);

			if (string.IsNullOrEmpty(name))
			{
				// Nothing we can do.
				return;
			}

			object value = context.ResolveValue(name, false);
			if (value == null && !isNegatedSection)
			{
				// No value, nothing we can do :-(
				return;
			}

			if ((value is IEnumerable) && !(value is string) && !isNegatedSection)
			{
				RenderEnumerable((IEnumerable)value, context, children, null);
			}
			else
			{
				bool isTruthy = IsTruthy(value);

				// Treat this as a conditional block.
				if (isTruthy != isNegatedSection)
				{
					if (isTruthy)
					{
						// Create a scope around the value.
						using (var scope = context.BeginScope(value))
						{
							RenderChildren(children, context);
						}
					}
					else
					{
						RenderChildren(children, context);
					}
				}
			}
		}
		/// <summary>
		/// Collapses the next whitespace element from the given block, offset by the child element.
		/// </summary>
		/// <param name="block">The block.</param>
		/// <param name="element">The child element.</param>
		private void CollapseNextWhiteSpace(Block block, SyntaxTreeNode element)
		{
			if (block == null)
			{
				return;
			}

			var children = block.Children.ToList();
			int index = children.IndexOf(element);
			if (index < (children.Count - 1))
			{
				var potential = children[index + 1] as Span;
				if (potential != null && potential.Kind == SpanKind.WhiteSpace)
				{
					potential.Collapsed = true;
				}
			}
		}
		/// <summary>
		/// Parses the conditional blocks.
		/// </summary>
		/// <param name="target">The target.</param>
		/// <returns>The set of parsed conditional blocks.</returns>
		private IEnumerable<Tuple<Block, List<SyntaxTreeNode>>> ParseConditionalBlocks(Block target)
		{
			var result = new List<Tuple<Block, List<SyntaxTreeNode>>>();

			Block current = null;
			var nodes = new List<SyntaxTreeNode>();

			var children = target.Children.ToList();
			children.RemoveAt(children.Count - 1);

			foreach (var node in children)
			{
				bool isNewElement = false;
				if (node.IsBlock)
				{
					var block = (Block)node;
					if (block.Type == BlockType.TagElement && (block.Name == "if" || block.Name == "elseif" || block.Name == "else" || block.Name == "^"))
					{
						if (current != null)
						{
							result.Add(Tuple.Create(current, nodes));
							nodes = new List<SyntaxTreeNode>();
						}
						current = block;
						isNewElement = true;
					}
				}

				if (!isNewElement)
				{
					nodes.Add(node);
				}
			}

			if (current != null)
			{
				result.Add(Tuple.Create(current, nodes));
			}

			return result;
		}
		/// <inheritdoc />
		public override void Render(Block target, RenderContext context, TextWriter writer)
		{
			// 1. Figure out branching blocks.
			// 2. For each branching block (first to last), resolve conditional argument.
			var blocks = ParseConditionalBlocks(target);

			foreach (var block in blocks)
			{
				var arguments = GetArgumentsAndMappedParameters(block.Item1, context);
				if (block.Item1.Name == "if" || block.Item1.Name == "elseif")
				{
					if (IsTruthy(arguments.Item1[0]))
					{
						RenderChildren(block.Item2, context);
						break;
					}
				}
				else
				{
					RenderChildren(block.Item2, context);
					break;
				}
			}
		}
Esempio n. 11
0
		/// <summary>
		/// Initializes a new instance of the <see cref="ParserResults"/> class.
		/// </summary>
		/// <param name="succes">We parsing succesful?</param>
		/// <param name="document">The document.</param>
		/// <param name="errors">The errors.</param>
		public ParserResults(bool succes, Block document, IList<Error> errors)
		{
			Success = succes;
			Document = document;
			Errors = errors;
		}
Esempio n. 12
0
		/// <summary>
		/// Initializes a new instance of the <see cref="ParserResults"/> class.
		/// </summary>
		/// <param name="document">The document.</param>
		/// <param name="errors">The errors.</param>
		public ParserResults(Block document, IList<Error> errors)
			: this(errors == null || errors.Count == 0, document, errors)
		{
			
		}
		/// <inheritdoc />
		protected override void Render(Block block, object[] arguments, Dictionary<string, object> maps, RenderContext context, TextWriter writer) { }
Esempio n. 14
0
		private void ParserTest(string content, Block document, TagProvidersCollection providers = null)
		{
			providers = providers ?? TagProvidersCollection.Default;

			var output = new StringBuilder();
			using (var reader = new StringReader(content))
			{
				using (var source = new SeekableTextReader(reader))
				{
					var errors = new ParserErrorSink();
					var parser = new HandlebarsParser();

					var context = new ParserContext(source, parser, errors, providers);
					parser.Context = context;

					parser.ParseDocument();

					var results = context.CompleteParse();

					var comparer = new EquivalanceComparer(output, 0);

					Assert.True(comparer.Equals(document, results.Document), output.ToString());
				}
			}
		}
Esempio n. 15
0
		/// <summary>
		/// Processed before any child nodes of a block are visited.
		/// </summary>
		/// <param name="block">The block.</param>
		public virtual void VisitStartBlock(Block block) { }
Esempio n. 16
0
		/// <summary>
		/// Processed after a all child nodes of a block are visited.
		/// </summary>
		/// <param name="block">The block.</param>
		public virtual void VisitEndBlock(Block block) { }