using System; using System.Collections.Generic; using System.IO; using Mustache.Properties; namespace Mustache { /// /// Defines the attributes of a custom tag. /// public abstract class TagDefinition { /// /// Initializes a new instance of a TagDefinition. /// /// The name of the tag. /// The name of the tag is null or blank. protected TagDefinition(string tagName) : this(tagName, false) { } /// /// Initializes a new instance of a TagDefinition. /// /// The name of the tag. /// Specifies whether the tag is built-in or not. Checks are not performed on the names of built-in tags. internal TagDefinition(string tagName, bool isBuiltIn) { if (!isBuiltIn && !RegexHelper.IsValidIdentifier(tagName)) { throw new ArgumentException(Resources.BlankTagName, "tagName"); } Name = tagName; } /// /// Gets the name of the tag. /// public string Name { get; private set; } internal bool IsSetter { get { return GetIsSetter(); } } protected virtual bool GetIsSetter() { return false; } /// /// Gets whether the tag is limited to the parent tag's context. /// internal bool IsContextSensitive { get { return GetIsContextSensitive(); } } /// /// Gets whether a tag is limited to the parent tag's context. /// protected virtual bool GetIsContextSensitive() { return false; } /// /// Gets the parameters that are defined for the tag. /// internal IEnumerable Parameters { get { return GetParameters(); } } /// /// Specifies which parameters are passed to the tag. /// /// The tag parameters. protected virtual IEnumerable GetParameters() { return new TagParameter[] { }; } /// /// Gets whether the tag contains content. /// internal bool HasContent { get { return GetHasContent(); } } /// /// Gets whether tag has content. /// /// True if the tag has content; otherwise, false. protected abstract bool GetHasContent(); /// /// Gets the tags that can indicate that the tag has closed. /// This field is only used if no closing tag is expected. /// internal IEnumerable ClosingTags { get { return GetClosingTags(); } } protected virtual IEnumerable GetClosingTags() { if (HasContent) { return new string[] { Name }; } else { return new string[] { }; } } /// /// Gets the tags that are in scope within the current tag. /// internal IEnumerable ChildTags { get { return GetChildTags(); } } /// /// Specifies which tags are scoped under the current tag. /// /// The child tag definitions. protected virtual IEnumerable GetChildTags() { return new string[] { }; } /// /// Gets the parameter that will be used to create a new child scope. /// /// The parameter that will be used to create a new child scope -or- null if no new scope is created. public abstract IEnumerable GetChildContextParameters(); /// /// Gets the context to use when building the inner text of the tag. /// /// The text writer passed /// The current key scope. /// The arguments passed to the tag. /// The scope to use when building the inner text of the tag. public virtual IEnumerable GetChildContext( TextWriter writer, Scope keyScope, Dictionary arguments, Scope contextScope) { NestedContext context = new NestedContext() { KeyScope = keyScope, Writer = writer, ContextScope = contextScope.CreateChildScope() }; yield return context; } /// /// Applies additional formatting to the inner text of the tag. /// /// The text writer to write to. /// The arguments passed to the tag. /// The data associated to the context. public virtual void GetText(TextWriter writer, Dictionary arguments, Scope context) { } /// /// Consolidates the text in the given writer to a string, using the given arguments as necessary. /// /// The writer containing the text to consolidate. /// The arguments passed to the tag. /// The consolidated string. public virtual string ConsolidateWriter(TextWriter writer, Dictionary arguments) { return writer.ToString(); } /// /// Requests which generator group to associate the given tag type. /// /// The child tag definition being grouped. /// The name of the group to associate the given tag with. public virtual bool ShouldCreateSecondaryGroup(TagDefinition definition) { return false; } /// /// Gets whether the group with the given name should have text generated for them. /// /// The arguments passed to the tag. /// True if text should be generated for the group; otherwise, false. public virtual bool ShouldGeneratePrimaryGroup(Dictionary arguments) { return true; } } }