Esempio n. 1
0
 /// <summary>
 /// Chooses the replacement open and close tags to use for rendering based off whether we are
 /// rendering an ordered or unordered list.
 /// </summary>
 /// <param name="openTag">The <see cref="IOpenTagInstance"/></param>
 /// <param name="replacementOpenTag">Returns the replacement open tag to use</param>
 /// <param name="replacementCloseTag">Returns the replacement close tag to use</param>
 private void ChooseReplacementTags(IOpenTagInstance openTag, out string replacementOpenTag, out string replacementCloseTag)
 {
     if ((bool)openTag.Attributes["Ordered"])
     {
         replacementOpenTag  = REPLACEMENT_OLIST_OPEN_TAG;
         replacementCloseTag = REPLACEMENT_OLIST_CLOSE_TAG;
     }
     else
     {
         replacementOpenTag  = REPLACEMENT_UOLIST_OPEN_TAG;
         replacementCloseTag = REPLACEMENT_UOLIST_CLOSE_TAG;
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Replacement function that writes the rendered open tag for colour BBcode open tags
        /// </summary>
        /// <param name="openTagInstance">The <see cref="ITagInstance"/></param>
        /// <returns>The rendered XHTML tag</returns>
        private static string ReplacementOpenTagFactoryFunction(IOpenTagInstance openTagInstance)
        {
            string colour;

            if (openTagInstance.Attributes.ContainsKey("Hex"))
            {
                colour = (string)openTagInstance.Attributes["Hex"];
            }
            else
            {
                colour = (string)openTagInstance.Attributes["Name"];
            }

            return(String.Format(REPLACEMENT_OPEN_TAG_FORMAT_STRING, colour));
        }
Esempio n. 3
0
        /// <summary>
        /// Causes the <see cref="ITagDefinition"/> to render all of its <see cref="ITagInstance"/>s into XHTML.
        /// </summary>
        /// <remarks>
        /// This method is always called after <see cref="ITagDefinition.RemoveWhitespace"/> is called on any
        /// <see cref="ITagDefinition"/>. The order in which this method is called across the different
        /// <see cref="ITagDefinition"/>s is undefined.
        /// </remarks>
        /// <param name="context">
        /// The <see cref="IRenderContext"/> contains all the <see cref="ITagInstance"/>s, the input text,
        /// and methods that allow for the rendering of <see cref="ITagInstance"/>s.
        /// </param>
        public override void Render(IRenderContext context)
        {
            IEnumerable <IOpenTagInstance> tagInstances = context.Tags.Where(t => t.ParentDefinition == this)
                                                          .OfType <IOpenTagInstance>();

            foreach (IOpenTagInstance openTag in tagInstances)
            {
                ICloseTagInstance closeTag = openTag.CloseTag;

                string replacementOpenTag = REPLACEMENT_OPEN_TAG;
                if (openTag.Attributes.ContainsKey("Username"))
                {
                    replacementOpenTag += String.Format(AUTHOR_TAG_FORMAT_STRING, WebUtility.HtmlEncode((string)openTag.Attributes["Username"]));
                }
                context.RenderTag(openTag, replacementOpenTag, true);

                //Wrap all content that is not inside an block element tag in P tags
                ITagInstance afterTag = openTag;
                while (afterTag != null)
                {
                    //Find the next block element tag nested inside openTag
                    IOpenTagInstance untilTag = context.GetTagsAfter(afterTag)
                                                .TakeWhile(t => t != closeTag)                                                   //Take until the close tag
                                                .WhereStackDepthIs(0)                                                            //Only tags immediately nested inside openTag
                                                .Where(t => t.RendersToInlineElement == false)
                                                .OfType <IOpenTagInstance>()
                                                .FirstOrDefault();

                    if (untilTag != null)
                    {
                        WrapTextBetweenTagsInPTags(afterTag, untilTag, context);
                        afterTag = untilTag.CloseTag;
                    }
                    else
                    {
                        WrapTextBetweenTagsInPTags(afterTag, closeTag, context);
                        afterTag = null;
                    }
                }

                context.RenderTag(closeTag, REPLACEMENT_CLOSE_TAG, true);
            }

            context.RegisterRenderCacheability(true);
        }
 /// <summary>
 /// Asks this <see cref="IOpenTagInstance"/> whether the specified <paramref name="tagInstance"/>is allowed
 /// to be inside it (ie before this open tag's close tag occurs).
 /// </summary>
 /// <param name="tagInstance">
 /// The <see cref="IOpenTagInstance"/> which is trying to reside before the this tag's
 /// <see cref="ICloseTagInstance"/>.
 /// </param>
 /// <param name="context">The <see cref="ValidationContext"/></param>
 /// <returns>
 /// True if this tag objects to the specified <paramref name="tagInstance"/> (which causes the
 /// <paramref name="tagInstance"/> to be removed and therefore ignored during rendering),
 /// false if it is okay for the <paramref name="tagInstance"/> to be there.
 /// </returns>
 public bool CheckForVetoAgainstAnotherTag(IOpenTagInstance tagInstance, ValidationContext context)
 {
     return(_OpenTagVetoRulesSet.OtherTagVetoRules.Any(r => r.CheckForVeto(tagInstance, context)));
 }
Esempio n. 5
0
        /// <summary>
        /// Validates the BBCode tags and ensures they respect the rules they define. For example, some tags
        /// disallow other tags inside them. This is where those rules are enforced and errant tags
        /// (<see cref="ITagInstance"/>s) are removed.
        /// </summary>
        /// <param name="context">The <see cref="ValidationContext"/></param>
        private void ValidateAndRepairSyntax(ValidationContext context)
        {
            for (int i = 0; i < context.Tags.Count; i++)
            {
                ITagInstance tagInstance = context.Tags[i];
                bool         vetoed      = CheckForPreviousTagOverlap(context, i);

                if (vetoed == false && tagInstance is IOpenTagInstance)
                {
                    IOpenTagInstance openTagInstance = (IOpenTagInstance)tagInstance;

                    //If any other tag vetoes this one, OR this tag vetoes itself
                    vetoed = context.OpenTagStack.Any(t => t.CheckForVetoAgainstAnotherTag(openTagInstance, context)) ||
                             openTagInstance.CheckForSelfVeto(context);

                    if (vetoed == false)
                    {
                        context.OpenTagStack.Push(openTagInstance);
                    }
                }

                if (vetoed == false && tagInstance is ICloseTagInstance)
                {
                    //If we find a close tag without any open tag, OR
                    //if the current innermost tag (top of the stack) is not the open tag for this close tag
                    vetoed = context.OpenTagStack.Any() == false ||
                             context.OpenTagStack.Peek().ParentDefinition != tagInstance.ParentDefinition;

                    if (vetoed == false)
                    {
                        IOpenTagInstance openTagInstance = context.OpenTagStack.Pop();
                        openTagInstance.CloseTag = (ICloseTagInstance)tagInstance;
                    }
                }

                if (vetoed)
                {
                    context.Tags.RemoveAt(i);
                    i--;
                }
            }

            //Close any tags that were left open
            while (context.OpenTagStack.Any())
            {
                IOpenTagInstance openTagInstance = context.OpenTagStack.Peek();

                string            tagText;
                ICloseTagInstance closeTag = openTagInstance.ParentDefinition.MakeCloseTagFor(openTagInstance, context.InputString.Length, out tagText);
                if (closeTag.CheckIfValidClose(context))
                {
                    context.InputString.Append(tagText);
                    context.Tags.Add(closeTag);
                    openTagInstance.CloseTag = closeTag;
                }
                else
                {
                    context.Tags.Remove(openTagInstance);
                }

                context.OpenTagStack.Pop();
            }
        }
        /// <summary>
        /// Replacement function that writes the rendered open tag for size BBcode open tags
        /// </summary>
        /// <param name="openTagInstance">The <see cref="IOpenTagInstance"/></param>
        /// <returns>The rendered XHTML tag</returns>
        private static string ReplacementOpenTagFactoryFunction(IOpenTagInstance openTagInstance)
        {
            int size = (int)openTagInstance.Attributes["Size"];

            return(String.Format(REPLACEMENT_OPEN_TAG_FORMAT_STRING, size));
        }
 /// <summary>
 /// Makes a closing tag instance for the specified <see cref="IOpenTagInstance"/>. Used to create closing
 /// tags for unclosed tag pairs during tag validation.
 /// </summary>
 /// <param name="openTagInstance">The <see cref="IOpenTagInstance"/> that needs a closing tag</param>
 /// <param name="firstCharIndex">The index of where the first character of the close tag must be</param>
 /// <param name="tagText">
 /// Returns the text of the tag, which will be added to the input string by the validator
 /// </param>
 /// <returns>The <see cref="ICloseTagInstance"/></returns>
 public virtual ICloseTagInstance MakeCloseTagFor(IOpenTagInstance openTagInstance, int firstCharIndex, out string tagText)
 {
     tagText = _CloseTag;
     return(new CloseTagInstance(new CharRange(firstCharIndex, _CloseTag.Length), this, _RendersToInlineElement, _CloseTagVetoRules, Enumerable.Empty <KeyValuePair <string, object> >()));
 }
Esempio n. 8
0
 /// <summary>
 /// Makes a closing tag instance for the specified <see cref="IOpenTagInstance"/>. Used to create closing
 /// tags for unclosed tag pairs during tag validation.
 /// </summary>
 /// <param name="openTagInstance">The <see cref="IOpenTagInstance"/> that needs a closing tag</param>
 /// <param name="firstCharIndex">The index of where the first character of the close tag must be</param>
 /// <param name="tagText">
 /// Returns the text of the tag, which will be added to the input string by the validator
 /// </param>
 /// <returns>The <see cref="ICloseTagInstance"/></returns>
 public ICloseTagInstance MakeCloseTagFor(IOpenTagInstance openTagInstance, int firstCharIndex, out string tagText)
 {
     tagText = CloseTag;
     return(new CloseTagInstance(new CharRange(firstCharIndex, CloseTag.Length), this, false, Enumerable.Empty <IVetoRule>(), Enumerable.Empty <KeyValuePair <string, object> >()));
 }