private void ConvertChildrenToControlBlocks(LoveBlock block) { if (block.Children.Count == 0) { return; } // Find inner most control block var regexControlStart = @"\s*((?:if)|(?:foreach))\s*\((.*)\)\s*({)?\s*"; var regexControlEnd = @"\s*}\s*"; var childrenWithIndex = block.Children .Select((Child, Index) => new { Child, Index }).ToList(); var controlBlockStarts = childrenWithIndex .Where(c => c.Child is LoveBinding && Regex.IsMatch((c.Child as LoveBinding).Content, regexControlStart)).ToList(); var controlBlockEnds = childrenWithIndex .Where(c => c.Child is LoveBinding && Regex.IsMatch((c.Child as LoveBinding).Content, regexControlEnd)).ToList(); if (controlBlockStarts.Any()) { var lastStart = controlBlockStarts.Last(); var nextEnd = controlBlockEnds.Where(c => c.Index > lastStart.Index).FirstOrDefault(); var blockSet = childrenWithIndex.Where(c => c.Index >= lastStart.Index && c.Index <= nextEnd.Index).ToList(); var m = Regex.Match((lastStart.Child as LoveBinding).Content, regexControlStart); var controlType = m.Groups[1].Value; var statement = m.Groups[2].Value; var openBraces = m.Groups.Count > 2 ? m.Groups[3].Value : ""; LoveBlock controlBlock = CreateControlBlock(blockSet.Select(c => c.Child).ToList(), controlType, statement, openBraces); if (controlBlock == null) { // If failed, stick it in a regular block (to avoid a loop) controlBlock = new LoveBlock(lastStart.Child.Start, blockSet.Sum(b => b.Child.Length)); controlBlock.Children.AddRange(blockSet.Select(c => c.Child)); } // Switch the old blocks for the new for (int i = 0; i < blockSet.Count; i++) { block.Children.RemoveAt(blockSet.First().Index); } block.Children.Add(controlBlock); } if (controlBlockStarts.Count() > 1) { // Repeat if needed ConvertChildrenToControlBlocks(block); } }
private LoveControlBlock CreateControlBlock(List <LoveNode> blockSet, string controlType, string statement, string openBraces) { var controlStart = blockSet.First() as LoveBinding; var controlEnd = blockSet.Last(); var hasClosingBraces = openBraces == "{" && controlEnd is LoveBinding && (controlEnd as LoveBinding).Content.Trim() == "}"; var bodyLength = blockSet.Count - 1; bodyLength -= hasClosingBraces ? 1 : 0; var bodyChildren = blockSet.Skip(1).Take(bodyLength); var bodyBlock = new LoveBlock(bodyChildren.First().Start, bodyChildren.Sum(c => c.Length)); bodyBlock.Children.AddRange(bodyChildren); if (controlType == "if") { LoveBindingBase statementBinding = CreateStatement(controlStart, statement); return(new LoveIfBlock(controlStart.Start, controlEnd.Start - controlStart.Start + controlEnd.Length, statementBinding, bodyBlock)); } else if (controlType == "foreach") { var regexForeach = @"\s*(\S+)\s+in\s+(\S+)\s*"; var m = Regex.Match(statement, regexForeach); if (m.Success) { var itemName = m.Groups[1].Value; statement = m.Groups[2].Value; var itemNameSpan = new LoveName(controlStart.Start + controlStart.Content.IndexOf(itemName), itemName.Length, itemName); LoveBindingBase statementBinding = CreateStatement(controlStart, statement); return(new LoveForeachBlock(controlStart.Start, controlEnd.Start - controlStart.Start + controlEnd.Length, itemNameSpan, statementBinding, bodyBlock)); } else { return(null); } } return(null); }
private void SimplifyChildren(LoveBlock block) { for (int i = 0; i < block.Children.Count; i++) { var child = block.Children[i]; // Go deeper if (child is LoveBlock) { SimplifyChildren(child as LoveBlock); } // Remove Bindings with only whitespace if (child is LoveBindingBase) { var cBinding = child as LoveBindingBase; if (string.IsNullOrEmpty(cBinding.Content.Trim())) { block.Children.RemoveAt(i); i--; continue; } } // Simplify child blocks if (child.GetType() == typeof(LoveBlock)) { var cBlock = child as LoveBlock; // Remove if no children if (cBlock.Children.Count == 0) { block.Children.RemoveAt(i); i--; continue; } // Flatten if only one child if (cBlock.Children.Count == 1) { block.Children[i] = cBlock.Children[0]; } } } }
public static LoveBlock MapBinding(LoveMarkupExpression htmlHelperExpression, string normalHtml, string simpleHtml, string simpleExpression) { var indices = normalHtml.Find(simpleHtml).ToList(); if (indices.Count == 0) { // Apparently Static var b = new LoveBlock(0, 0); b.Children.Add(new LoveMarkup(0, 0, normalHtml)); return(b); } else { // Create a block with bindings var b = new LoveBlock(0, 0); // Add before binding b.Children.Add(new LoveMarkup(0, 0, normalHtml.Substring(0, indices[0]))); for (int i = 0; i < indices.Count; i++) { var index = indices[i]; var nextIndex = i < indices.Count - 1 ? indices[i + 1] : (int?)null; // Add binding var bindingContent = simpleExpression; b.Children.Add(new LoveBinding(0, 0, bindingContent)); // Add after binding var afterIndex = index + simpleHtml.Length; if (nextIndex.HasValue) { b.Children.Add(new LoveMarkup(0, 0, normalHtml.Substring(afterIndex, nextIndex.Value - afterIndex))); } else { b.Children.Add(new LoveMarkup(0, 0, normalHtml.Substring(afterIndex))); } } return(b); } }
private void HandleModelStatement(LoveBlock document) { if (document.Children.Count <= 1) { return; } var first = document.Children[0] as LoveSpan; var second = document.Children[1] as LoveSpan; // Go into 2nd child if block if (document.Children[1].GetType() == typeof(LoveBlock)) { var secondBlock = (document.Children[1] as LoveBlock); second = secondBlock.Children.FirstOrDefault() as LoveSpan; } if (first == null || second == null) { return; } var modelMatch = Regex.Match(second.Content, @"^(\s*[A-Za-z0-9\.]+(?:\r\n)?)([\s\S]*)?$"); if (first.Content == "model" && modelMatch.Success) { var modelLine = modelMatch.Groups[1].Value; var remaining = modelMatch.Groups.Count > 1 ? modelMatch.Groups[2].Value : ""; document.Children[0] = new LoveModelStatement(first.Start, first.Length + modelLine.Length, modelLine.Trim()); if (!string.IsNullOrWhiteSpace(remaining)) { second.Modify(second.Start + modelLine.Length, remaining.Length, remaining); } else { second.Modify(0, 0, ""); SimplifyChildren(document); } } }
private LoveBlock VisitBlock(Block block) { // Handle regular block var lBlock = new LoveBlock(block.Start.AbsoluteIndex, block.Length); foreach (var c in block.Children) { var node = VisitNode(c); if (node != null) { lBlock.Children.Add(node); } } // Merge blocks of same type var newChildren = new List <LoveNode>(); LoveNode newChild = null; foreach (var c in lBlock.Children) { if (newChild != null && newChild.GetType() == c.GetType() && c is LoveSpan) { var cSpan = c as LoveSpan; var newSpan = newChild as LoveSpan; if (cSpan is LoveBinding) { newChild = new LoveBinding(newSpan.Start, newSpan.Length + cSpan.Length, newSpan.Content + cSpan.Content); } else if (cSpan is LoveMarkup) { newChild = new LoveMarkup(newSpan.Start, newSpan.Length + cSpan.Length, newSpan.Content + cSpan.Content); } else if (cSpan is LoveMarkupExpression) { newChild = new LoveMarkupExpression(newSpan.Start, newSpan.Length + cSpan.Length, newSpan.Content + cSpan.Content); } } else { if (newChild != null) { newChildren.Add(newChild); newChild = null; } newChild = c; } } if (newChild != null) { newChildren.Add(newChild); newChild = null; } lBlock.Children.Clear(); lBlock.Children.AddRange(newChildren); if (lBlock.Children.Count == 0) { return(null); } // Simplify children for (int i = 0; i < lBlock.Children.Count; i++) { var child = lBlock.Children[i]; // Convert bindings to specific bindings if possible if (child is LoveBinding) { lBlock.Children[i] = ConvertBinding(child as LoveBinding); } } ConvertChildrenToControlBlocks(lBlock); //// Convert to control blocks if Possible //var cBlock = ConvertToControlBlock(lBlock); //if (cBlock != null) { return cBlock; } return(lBlock); }
private void VisitBlock(LoveTranslation translation, LoveBlock loveBlock, object model) { throw new NotImplementedException(); }