Ejemplo n.º 1
0
        /// <summary>
        /// Internal method for rendering images
        /// </summary>
        public static string RenderColor(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if ((Node.Attribute ?? "").Trim() == "")
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("Missing attribute in [color] tag.");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            if (!Regex.IsMatch(Node.Attribute.Trim(), "^#?[a-z0-9]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase))
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("Invalid color in [color] tag. Expected either color name or hexadecimal color");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            return("<span style=\"color:" + Node.Attribute.Trim() + "\">"
                   + Node.Children.ToHtml(ThrowOnError, LookupTable)
                   + "</span>");
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Internal method for rendering a BBCode tag that corresponds to a class on the HTML tag
 /// </summary>
 public static string ClassConvert(BBCodeNode Node, bool ThrowOnError, object LookupTable)
 {
     string converted;
     switch (Node.TagName)
     {
         case "s":
         case "S":
             converted = "<span style=\"text-decoration: line-through\">"
             + Node.Children.ToHtml(ThrowOnError, LookupTable)
             + "</span>";
             break;
         case "u":
         case "U":
             converted = "<span style=\"text-decoration: underline\">"
             + Node.Children.ToHtml(ThrowOnError, LookupTable)
             + "</span>";
             break;
         case "size":
             converted = string.Format("<span style=\"font-size: {0}px\">", Node.Attribute)
             + Node.Children.ToHtml(ThrowOnError, LookupTable)
             + "</span>";
             break;
         default:
             converted = "<div class=\"" + Node.TagName + "\">"
             + Node.Children.ToHtml(ThrowOnError, LookupTable)
             + "</div>";
             break;
     }
     return converted;
 }
        string ParseCode(BBCodeNode node)
        {
            // In <pre> tags, line breaks were determinated by escape sequences. Additional <br /> as our parser creates would result in another line break (= empty line), so we remove it in this special case
            string noBrInnerHtml = node.InnerHtml.Replace("<br />", "");

            return($"<pre>{noBrInnerHtml}</pre>");
        }
Ejemplo n.º 4
0
        string ParseNode(BBCodeNode node, BBCode code = null)
        {
            // Text only nodes doesn't need any parsing
            if (string.IsNullOrEmpty(node.TagName))
            {
                string innerHtml = ParseNewLines(node.InnerContent);
                return(innerHtml);
            }

            if (code == null)
            {
                code = GetBBCodeForNode(node);
            }
            if (code == null)
            {
                string innerHtml = node.OpenTag;

                // If we find unknown bbcodes, try parsing their inner content html and display the raw outer bbcode so that the user know it's not parseable.
                if (node.Childs != null)
                {
                    node.Childs.ForEach(childNode => innerHtml += ParseNode(childNode));
                }
                else
                {
                    // We also end up here if square brackets were used in other ways like quote, which shouldnt got destroyed: "He [mr xyz] said that..."
                    // In this case, InnerContent is the content after the brackets and childs may be null. No childs exists.
                    innerHtml += ParseNewLines(node.InnerContent);
                }
                // ParseNewLines() call is exceptional here. Regularly it's handled by GetNodeInnerContentHtml()
                return(innerHtml + node.CloseTag);
            }

            string html = "";

            if (code.ParserFunc != null)
            {
                // From a parser function, we expect to handle the ENTIRE node. Only for this reason, the inner html is required and only provided here
                node.InnerHtml = GetNodeInnerContentHtml(node, code.NestedChild);
                html           = code.ParserFunc(node);
            }
            else
            {
                string openTag = code.HtmlTag;
                if (!string.IsNullOrEmpty(code.ArgumentHtmlAttribute))
                {
                    // When theres no custom display text (e.g. [url]https://ecosia.org[/url]) we set the argument like in [url=https://ecosia.org]https://ecosia.org[/url] to have a unified link target
                    if (code.BBCodeName == "url" && node.Argument == null)
                    {
                        node.Argument = node.InnerContent;
                    }

                    openTag = openTag.Replace(">", $" {code.ArgumentHtmlAttribute}=\"{node.Argument}\">");
                }
                string closeTag = code.HtmlTag.Replace("<", "</");

                html += openTag + GetNodeInnerContentHtml(node, code.NestedChild) + closeTag;
            }
            return(html);
        }
        /// <summary>
        /// Fetches embedded Razor views for more complex HTML code from the dll (requires to set "build" to "embedded ressource" in the propertys of the cshtml file)
        /// </summary>
        string GetEmbeddRazorTemplate(string name, BBCodeNode node)
        {
            string key = $"Html.Templates.{name}.cshtml";

            string template = razor.CompileRenderAsync(key, node).Result;

            return(template);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Internal method for rendering a BBCode tag that corresponds 1:1 with an HTML tag
        /// </summary>
        public static string DirectConvert(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if (Node.Singular)
                return "<" + Node.TagName + " />";

            return "<" + Node.TagName + ">"
                    + Node.Children.ToHtml(ThrowOnError, LookupTable)
                    + "</" + Node.TagName + ">";
        }
Ejemplo n.º 7
0
        BBCode GetBBCodeForNode(BBCodeNode node)
        {
            // First search for exact open tag to match [list=1] pattern before non-specific [list] pattern
            var code = bbCodes.FirstOrDefault(x => x.BBCodeTag == node.OpenTag.ToLower());

            if (code == null)
            {
                code = bbCodes.FirstOrDefault(x => x.BBCodeName == node.TagName.ToLower());
            }
            return(code);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Internal method for rendering a BBCode tag that corresponds 1:1 with an HTML tag
        /// </summary>
        public static string DirectConvert(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if (Node.Singular)
            {
                return("<" + Node.TagName + " />");
            }

            return("<" + Node.TagName + ">"
                   + Node.Children.ToHtml(ThrowOnError, LookupTable)
                   + "</" + Node.TagName + ">");
        }
 string ParseHadlines(BBCodeNode node)
 {
     if (!int.TryParse(node.Argument, out int headlineSize))
     {
         return($"{node.OpenTag}{node.InnerHtml}{node.CloseTag}");
     }
     if (headlineSize == 1)
     {
         return($"<small class='text-muted d-block'>{node.InnerHtml}</small>");
     }
     // ToDo: May replace by hX headlines
     return($"<font size='{headlineSize}'>{node.InnerHtml}</font>");
 }
Ejemplo n.º 10
0
        public static XmlNode ToXml(this BBCodeNode obj, XmlDocument xdoc)
        {
            var el = xdoc.CreateElement(obj.TagName);

            el.SetAttribute("attribute", obj.Attribute);

            if (!obj.Singular)
            {
                foreach (var c in obj.Children)
                {
                    el.AppendChild(c.ToXml(xdoc));
                }
            }

            return(el);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Internal method for rendering images
        /// </summary>
        public static string RenderColor(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if ((Node.Attribute ?? "").Trim() == "")
                if (ThrowOnError)
                    throw new HtmlRenderException("Missing attribute in [color] tag.");
                else
                    return Error(Node, LookupTable);

            if (!Regex.IsMatch(Node.Attribute.Trim(), "^#?[a-z0-9]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase))
                if (ThrowOnError)
                    throw new HtmlRenderException("Invalid color in [color] tag. Expected either color name or hexadecimal color");
                else
                    return Error(Node, LookupTable);

            return "<span style=\"color:" + Node.Attribute.Trim() + "\">"
                    + Node.Children.ToHtml(ThrowOnError, LookupTable)
                    + "</span>";
        }
Ejemplo n.º 12
0
 static string Error(BBCodeNode Node, object LookupTable)
 {
     if (Node.Singular)
         return "["
                 + Node.TagName
                 + (((Node.Attribute ?? "").Trim() != "")
                     ? ("=" + HttpUtility.HtmlEncode(Node.Attribute ?? ""))
                     : (""))
                 + "]";
     else
         return "["
                 + Node.TagName
                 + (((Node.Attribute ?? "").Trim() != "")
                     ? ("=" + (HttpUtility.HtmlEncode(Node.Attribute ?? "")))
                     : (""))
                 + "]"
                 + Node.Children.ToHtml(false, LookupTable)
                 + "[/" + Node.TagName + "]";
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Internal method for rendering links
        /// </summary>
        public static string RenderLink(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if ((Node.Attribute ?? "").Trim() == "")
                if (Node.Children.Length != 0 && (Node.Children[0] as BBCodeTextNode) == null)
                    if (ThrowOnError)
                        throw new HtmlRenderException("[url] tag does not contain a URL attribute");
                    else
                        return Error(Node, LookupTable);
                else
                {
                    // support self-links such as [url]http://google.com[/url]
                    Node = ((BBCodeNode)Node.Clone()); // Nodes are mutable, and we don't want to mess with the original Node.
                    Node.Attribute = Node.Children[0].ToString();
                }

            Uri src = null;
            try
            {
                src = new Uri(Node.Attribute);
            }
            catch (UriFormatException)
            {
                if (ThrowOnError)
                    throw;
                return Error(Node, LookupTable);
            }

            if (!src.IsWellFormedOriginalString())
                if (ThrowOnError)
                    throw new HtmlRenderException("URL in [url] tag not well formed or relative");
                else
                    return Error(Node, LookupTable);

            if (!src.Scheme.Contains("http"))
                if (ThrowOnError)
                    throw new HtmlRenderException("URL scheme must be either HTTP or HTTPS");
                else
                    return Error(Node, LookupTable);

            return "<a href=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\">"
                    + Node.Children.ToHtml()
                    + "</a>";
        }
Ejemplo n.º 14
0
        private string GetNodeInnerContentHtml(BBCodeNode node, BBCode nestedChild = null)
        {
            string innerHtml = "";

            if (node.Childs != null)
            {
                // If we have childs, the Content attribute isn't interesting since it's contained in the childs
                node.Childs.ForEach(childNode => {
                    // Do not parse new lines here! This would also parse new lines on razor templates and create a lot of unwanted new lines. The last child will
                    // reach the else branch where only the new lines of inner content got parsed.
                    string childHtml = ParseNode(childNode, nestedChild);
                    innerHtml       += childHtml;
                });
            }
            else
            {
                innerHtml += ParseNewLines(node.InnerContent);
            }
            return(innerHtml);
        }
Ejemplo n.º 15
0
        void TrimNodeBeforeAfter(BBCodeNode node, List <BBCodeNode> nodes)
        {
            int index = nodes.IndexOf(node);
            // Only remove leading new lines on next node and trailing on previos. Do both would result in broken tags, e.g. wenn the previous item has \n\n at the beginning as delimiter
            int nextIndex = index + 1;

            if (nextIndex < nodes.Count)
            {
                var nextNode = nodes[nextIndex];
                nextNode.InnerContent = RemoveLeadingNewLines(nextNode.InnerContent);
            }

            int previousIndex = index - 1;

            if (previousIndex >= 0)
            {
                var previousNode = nodes[previousIndex];
                previousNode.InnerContent = RemoveTrailingNewLines(previousNode.InnerContent);
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Converts a BBCodeNode to HTML
        /// </summary>
        /// <param name="ThrowOnError">Whether or to throw an exception when an error is encountered. If false, errors will be silently ignored</param>
        /// <param name="LookupTable">A KeyValuePair&lt;string,HtmlRendererCallback&gt;[] containing valid BBCode tags and their HTML renderers</param>
        /// <returns>The HTML source as a string</returns>
        public static string ToHtml(this BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if ((Node as BBCodeTextNode) != null)
            {
                return(HttpUtility.HtmlEncode(Node.ToString()).Replace("\n", "<br />"));
            }

            var d = ((LookupT[])LookupTable).Where(x => ((LookupT)x).Key.ToLower() == Node.TagName.ToLower());

            if (d.Count() > 0)
            {
                return(((LookupT)d.First()).Value(Node, ThrowOnError, LookupTable));
            }

            if (ThrowOnError)
            {
                throw new HtmlRenderException("Unknown tag name '" + Node.TagName + "'");
            }

            return(Error(Node, LookupTable));
        }
        string ParseVideo(BBCodeNode node)
        {
            // Ignore malformed video tags
            if (string.IsNullOrEmpty(node.Argument) || !node.Argument.Contains(";"))
            {
                return(node.ToString());
            }

            var    argSegments = node.Argument.Split(';');
            string siteName    = argSegments[0].ToLower();
            string videoId     = argSegments[1];

            if (siteName == "youtube")
            {
                return(EmbeddedYouTube(videoId));
            }
            // Currently not supported providers
            string rawNode = node.ToString();

            return(rawNode);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Internal method for rendering images
        /// </summary>
        public static string RenderImage(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if (Node.Children.Length != 1)
                if (ThrowOnError)
                    throw new HtmlRenderException("[img] tag does not to contain image URL");
                else
                    return Error(Node, LookupTable);

            if ((Node.Children[0] as BBCodeTextNode) == null)
                if (ThrowOnError)
                    throw new HtmlRenderException("[img] tag does not to contain image URL");
                else
                    return Error(Node, LookupTable);

            Uri src = null;
            try
            {
                src = new Uri(Node.Children[0].ToString(), UriKind.Absolute);
            }
            catch (UriFormatException)
            {
                if (ThrowOnError)
                    throw;
                return Error(Node, LookupTable);
            }

            if (!src.IsWellFormedOriginalString())
                if (ThrowOnError)
                    throw new HtmlRenderException("Image URL in [img] tag not well formed or relative");
                else
                    return Error(Node, LookupTable);

            if (!src.Scheme.Contains("http"))
                if (ThrowOnError)
                    throw new HtmlRenderException("Image URL scheme must be either HTTP or HTTPS");
                else
                    return Error(Node, LookupTable);

            return "<img src=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\" alt=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\" />";
        }
        string ParseQuoteFunc(BBCodeNode node)
        {
            // Using InnerHTML to make sure that bbcode inside the quote (e.g. formattings or urls) got parsed, too
            string html = $"<blockquote class=\"blockquote\">{node.InnerHtml}";

            if (!string.IsNullOrEmpty(node.Argument))
            {
                var    authorSegments = node.Argument.Split(';');
                string author         = "";

                if (authorSegments.Length > 1)
                {
                    // ToDo: We need to verify on which page the post exists since this anker can't work if the post is on the previous or next page
                    author = $"<a href=\"#post{authorSegments[1]}\">{authorSegments[0]}</a>";
                }
                else
                {
                    author = authorSegments[0];
                }
                html += $"<footer class=\"blockquote-footer\">{author}</footer>";
            }
            return(html + "</blockquote>");
        }
Ejemplo n.º 20
0
 static string Error(BBCodeNode Node, object LookupTable)
 {
     if (Node.Singular)
     {
         return("["
                + Node.TagName
                + (((Node.Attribute ?? "").Trim() != "")
                     ? ("=" + HttpUtility.HtmlEncode(Node.Attribute ?? ""))
                     : (""))
                + "]");
     }
     else
     {
         return("["
                + Node.TagName
                + (((Node.Attribute ?? "").Trim() != "")
                     ? ("=" + (HttpUtility.HtmlEncode(Node.Attribute ?? "")))
                     : (""))
                + "]"
                + Node.Children.ToHtml(false, LookupTable)
                + "[/" + Node.TagName + "]");
     }
 }
Ejemplo n.º 21
0
 public static string RenderStrikethough(BBCodeNode Node, bool ThrowOnError, object LookupTable)
 {
     return("<del>" + Node.Children.ToHtml(ThrowOnError, LookupTable) + "</del>");
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Converts a BBCodeNode to HTML
 /// </summary>
 /// <param name="ThrowOnError">Whether or to throw an exception when an error is encountered. If false, errors will be silently ignored</param>
 /// <returns>The HTML source as a string</returns>
 public static string ToHtml(this BBCodeNode Node, bool ThrowOnError)
 {
     return(Node.ToHtml(ThrowOnError, (object)convertLookup));
 }
Ejemplo n.º 23
0
 /// <summary>
 /// Converts a BBCodeNode to HTML
 /// </summary>
 /// <returns>The HTML source as a string</returns>
 public static string ToHtml(this BBCodeNode Node)
 {
     return(Node.ToHtml(false));
 }
Ejemplo n.º 24
0
        /// <summary>
        /// Internal method for rendering links
        /// </summary>
        public static string RenderLink(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if ((Node.Attribute ?? "").Trim() == "")
            {
                if (Node.Children.Length != 0 && (Node.Children[0] as BBCodeTextNode) == null)
                {
                    if (ThrowOnError)
                    {
                        throw new HtmlRenderException("[url] tag does not contain a URL attribute");
                    }
                    else
                    {
                        return(Error(Node, LookupTable));
                    }
                }
                else
                {
                    // support self-links such as [url]http://google.com[/url]
                    Node           = ((BBCodeNode)Node.Clone()); // Nodes are mutable, and we don't want to mess with the original Node.
                    Node.Attribute = Node.Children[0].ToString();
                }
            }



            Uri src = null;

            try
            {
                src = new Uri(Node.Attribute);
            }
            catch (UriFormatException)
            {
                if (ThrowOnError)
                {
                    throw;
                }
                return(Error(Node, LookupTable));
            }

            if (!src.IsWellFormedOriginalString())
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("URL in [url] tag not well formed or relative");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            if (!src.Scheme.Contains("http"))
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("URL scheme must be either HTTP or HTTPS");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            return("<a href=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\">"
                   + Node.Children.ToHtml()
                   + "</a>");
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Internal method for rendering images
        /// </summary>
        public static string RenderImage(BBCodeNode Node, bool ThrowOnError, object LookupTable)
        {
            if (Node.Children.Length != 1)
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("[img] tag does not to contain image URL");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            if ((Node.Children[0] as BBCodeTextNode) == null)
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("[img] tag does not to contain image URL");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            Uri src = null;

            try
            {
                src = new Uri(Node.Children[0].ToString(), UriKind.Absolute);
            }
            catch (UriFormatException)
            {
                if (ThrowOnError)
                {
                    throw;
                }
                return(Error(Node, LookupTable));
            }

            if (!src.IsWellFormedOriginalString())
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("Image URL in [img] tag not well formed or relative");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            if (!src.Scheme.Contains("http"))
            {
                if (ThrowOnError)
                {
                    throw new HtmlRenderException("Image URL scheme must be either HTTP or HTTPS");
                }
                else
                {
                    return(Error(Node, LookupTable));
                }
            }

            return("<img src=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\" alt=\"" + HttpUtility.HtmlEncode(src.ToString()) + "\" />");
        }
Ejemplo n.º 26
0
 public static string RenderImg(BBCodeNode Node, bool ThrowOnError, object LookupTable)
 {
     return("<img class='img-fluid' src='" + Node.Children.ToHtml(ThrowOnError, LookupTable) + "'/>");
 }
Ejemplo n.º 27
0
 public static string RenderCode(BBCodeNode Node, bool ThrowOnError, object LookupTable)
 {
     return("<pre class=\"prettyprint linenums:1\">" + Node.Children.ToHtml(ThrowOnError, LookupTable) + "</pre>");
 }