private void ExecuteCustomTag(TagNode tag) { ITagHandler tagHandler = customTags[tag.TagName]; bool processInnerElements = tagHandler.TagEnter(this); foreach (TagNodeAttribute attribute in tag.Attributes) { if (!tagHandler.TagAttribute(attribute.Name, EvaluateExpression(attribute.Value))) throw new TemplateException(String.Format("{0} missing required attribute: {1}", tag.TagName, attribute.Name), tag.Line, tag.Column); } if (processInnerElements) { TextWriter saveWriter = writer; writer = new StringWriter(); string innerContent ; try { ProcessNodes(tag.ChildNodes); innerContent = writer.ToString(); } finally { writer = saveWriter; } tagHandler.TagContent(innerContent); } tagHandler.TagExit(this); }
private TagNode CollectForTag(TagNode tag, ref int index) { if (tag.Closed) // if self-closing tag, do not collect inner elements return tag; if (String.Compare(tag.TagName, "if", true) == 0) { tag = new IfTag(tag.Line, tag.Column, tag.GetAttributeValue("test")); } TagNode collectTag = tag; for (index++; index < nodes.Count; index++) { Node node = nodes[index]; if (node is TextNode) collectTag.ChildNodes.Add(node); else if (node is Expression) collectTag.ChildNodes.Add(node); else if (node is TagNode) { TagNode innerTag = (TagNode)node; if (string.Compare(innerTag.TagName, "else", true) == 0) { if (collectTag is IfTag) { ((IfTag)collectTag).FalseBranch = innerTag; collectTag = innerTag; } else throw new ParseException("else tag has to be positioned inside of if or elseif tag", innerTag.Line, innerTag.Column); } else if (string.Compare(innerTag.TagName, "elif", true) == 0) { if (collectTag is IfTag) { TagNode newTag = new IfTag(innerTag.Line, innerTag.Column, innerTag.GetAttributeValue("test")); ((IfTag)collectTag).FalseBranch = newTag; collectTag = newTag; } else throw new ParseException("elseif tag is not positioned properly", innerTag.Line, innerTag.Column); } else collectTag.ChildNodes.Add(CollectForTag(innerTag, ref index)); } else if (node is TagEnd) { TagEnd tagClose = (TagEnd)node; if (string.Compare(tag.TagName, tagClose.TagName, true) == 0) return tag; throw new ParseException("Close tag for " + tagClose.TagName + " doesn't have matching start tag.", node.Line, node.Column); } else throw new ParseException("Invalid node: " + node.GetType(), node.Line, node.Column); } throw new ParseException("Start tag: " + tag.TagName + " does not have matching end tag.", tag.Line, tag.Column); }
private TagNode ReadTag() { Consume(TokenKind.TagStart); Token name = Consume(TokenKind.ID); TagNode tag = new TagNode(name.Line, name.Column, name.Text); while (true) { if (Current.Kind == TokenKind.ID) tag.Attributes.Add(ReadAttribute()); else if (Current.Kind == TokenKind.TagEnd) { Consume(); break; } else if (Current.Kind == TokenKind.TagEndClose) { Consume(); tag.Closed = true; break; } else throw new ParseException("Invalid token in tag: " + Current.Kind, Current.Line, Current.Column); } return tag; }
private void ProcessTemplate(string name, TagNode tag) { if (customTags != null && customTags.ContainsKey(name)) { ExecuteCustomTag(tag); return; } Template useTemplate = currentTemplate.FindTemplate(name); if (useTemplate == null) throw new TemplateException(String.Format("Template '{0}' not found", name), tag.Line, tag.Column); // process inner elements and save content TextWriter saveWriter = writer; writer = new StringWriter(); string content = String.Empty; try { ProcessNodes(tag.ChildNodes); content = writer.ToString(); } finally { writer = saveWriter; } Template saveTemplate = currentTemplate; variableScope = new VariableScope(variableScope); variableScope["innerText"] = content; try { foreach (TagNodeAttribute attrib in tag.Attributes) { object val = EvaluateExpression(attrib.Value); variableScope[attrib.Name] = val; } currentTemplate = useTemplate; ProcessNodes(currentTemplate.Nodes); } finally { variableScope = variableScope.Parent; currentTemplate = saveTemplate; } }
private void ProcessTagSet(TagNode tag) { Expression expName = tag.GetAttributeValue("name"); if (expName == null) throw new TemplateException("Set is missing required attribute: name", tag.Line, tag.Column); Expression expValue = tag.GetAttributeValue("value"); if (expValue == null) throw new TemplateException("Set is missing required attribute: value", tag.Line, tag.Column); string name = EvaluateExpression(expName).ToString(); if (!Util.IsValidVariableName(name)) throw new TemplateException("'" + name + "' is not valid variable name.", expName.Line, expName.Column); object value = EvaluateExpression(expValue); SetValue(name, value); }
private void ProcessTag(TagNode tag) { string name = tag.TagName.ToLowerInvariant(); try { switch (name) { case "template": // skip those, because those are processed first break; case "else": ProcessNodes(tag.ChildNodes); break; case "apply": object val = EvaluateExpression(tag.GetAttributeValue("template")); ProcessTemplate(val.ToString(), tag); break; case "foreach": ProcessForEach(tag); break; case "for": ProcessFor(tag); break; case "set": ProcessTagSet(tag); break; default: ProcessTemplate(tag.TagName, tag); break; } } catch (TemplateException ex) { OnError(ex); } catch (Exception ex) { OnError("Error executing tag '" + name + "': " + ex.Message, tag.Line, tag.Column); } }
private void ProcessForEach(TagNode tag) { Expression expCollection = tag.GetAttributeValue("collection"); if (expCollection == null) throw new TemplateException("Foreach is missing required attribute: collection", tag.Line, tag.Column); object collection = EvaluateExpression(expCollection); if (!(collection is IEnumerable)) throw new TemplateException("Collection used in foreach has to be enumerable", tag.Line, tag.Column); Expression expVar = tag.GetAttributeValue("var"); if (expCollection == null) throw new TemplateException("Foreach is missing required attribute: var", tag.Line, tag.Column); object varObject = EvaluateExpression(expVar); if (varObject == null) varObject = "foreach"; string varname = varObject.ToString(); Expression expIndex = tag.GetAttributeValue("index"); string indexname = null; if (expIndex != null) { object obj = EvaluateExpression(expIndex); if (obj != null) indexname = obj.ToString(); } IEnumerator ienum = ((IEnumerable)collection).GetEnumerator(); int index = 0; while (ienum.MoveNext()) { index++; object value = ienum.Current; variableScope.SetValue(varname, value); if (indexname != null) variableScope.SetValue(indexname, index); ProcessNodes(tag.ChildNodes); } }
private void ProcessFor(TagNode tag) { Expression expFrom = tag.GetAttributeValue("from"); if (expFrom == null) throw new TemplateException("For is missing required attribute: from", tag.Line, tag.Column); Expression expTo = tag.GetAttributeValue("to"); if (expTo == null) throw new TemplateException("For is missing required attribute: to", tag.Line, tag.Column); Expression expIndex = tag.GetAttributeValue("index"); if (expIndex == null) throw new TemplateException("For is missing required attribute: index", tag.Line, tag.Column); object obj = EvaluateExpression(expIndex); string indexName = obj.ToString(); int start = Convert.ToInt32(EvaluateExpression(expFrom)); int end = Convert.ToInt32(EvaluateExpression(expTo)); for (int index = start; index < end; index++) { SetValue(indexName, index); //variables[indexName] = index; ProcessNodes(tag.ChildNodes); } }