2
Vote

Partial solution for font, color, size and indent parsing.

description

This is as far as I could get... it makes "legible" output of "standard bbcode", although it still needs a fix to handle spaces within font names.
 
 
        var parser = new BBCodeParser(new[]
            {
                new BBTag("b", "<b>", "</b>"), 
                new BBTag("i", "<span style=\"font-style:italic;\">", "</span>"), 
                new BBTag("u", "<span style=\"text-decoration:underline;\">", "</span>"), 
                new BBTag("code", "<pre class=\"prettyprint\">", "</pre>"), 
                new BBTag("img", "<img src=\"${content}\" />", "", false, true), 
                new BBTag("quote", "<blockquote>", "</blockquote>"), 
                new BBTag("list", "<ul>", "</ul>"), 
                new BBTag("*", "<li>", "</li>", true, false),
                new BBTag("url", "<a href=\"${href}\">", "</a>", new BBAttribute("href", ""), new BBAttribute("href", "href")), 
 
                // new BBTag("font", "FONT:${}", "ENDFONT", true, false),  // Parser Test
 
                new BBTag("font", "<span style=\"${font}\">", "</span>", true, true,
                    new BBAttribute("font", "font", 
                        // I'm just copying these functions from an example, but they seem to work.
                        attributeRenderingContext => string.IsNullOrEmpty(attributeRenderingContext.AttributeValue) 
                            ? "" 
                            : "font-family:" 
                            + attributeRenderingContext.AttributeValue + ";")),
 
                new BBTag("color", "<span style=\"${color}\">", "</span>", true, true,
                    new BBAttribute("color", "color", 
                        attributeRenderingContext => string.IsNullOrEmpty(attributeRenderingContext.AttributeValue) 
                            ? "" 
                            : "color:" 
                            + attributeRenderingContext.AttributeValue + ";")),
 
                new BBTag("size", "<!-- {$size} -->", "<!-- /size -->", true, true,  // TODO - Requires contentTransform (size=6 is 24pt)
                    new BBAttribute("size", "size", 
                        attributeRenderingContext => string.IsNullOrEmpty(attributeRenderingContext.AttributeValue) 
                            ? "" 
                            : "font-family:" 
                            + attributeRenderingContext.AttributeValue + ";")),
 
                new BBTag("indent", "<div style=\"padding-left: 40px\">", "</div>", true, true,
                    new BBAttribute("indent", "indent", 
                        attributeRenderingContext => String.Empty))
 
            });
 
        String html = parser.ToHtml(bbcode
            .Replace("[font=", "[font font=")
            .Replace("[color=", "[color color=")
            .Replace("[list=1", "[list")
            .Replace("[indent=", "[indent indent=")
            .Replace("[size=", "[size size="));
 
 
Where's the beef? There has to be a better way than this almighty hack.

comments

orwellophile wrote Dec 27, 2011 at 2:47 PM

Fixed the multi-word font names with:
    static string ParseAttributeValue(string input, ref int pos)
    {
[...]
        var endIndex = input.IndexOfAny("[]".ToCharArray(), end); // Changed from " []"
[..]
     }
Now at least my output look reasonably close to what it should, no unprocessed tags showing. Just have to implement [indent=2] and [size=x] correctly, which should be possible with on of the transformation options. Might also add an extra property called "tagname" that is added if ParseName() encounters an '='.

orwellophile wrote Dec 27, 2011 at 3:12 PM

sigh while attempting to modify source to allow [tag=value], I found that there is actually support for this functionality, using an empty attribute.

The following code works reasonably well for me, although it will still require the previously mentioned patch for multi-word font names.

protected void ProcessBBCode(String bbcode) {
        var parser = new BBCodeParser(new[]
            {
                new BBTag("b", "<b>", "</b>"), 
                new BBTag("i", "<span style=\"font-style:italic;\">", "</span>"), 
                new BBTag("u", "<span style=\"text-decoration:underline;\">", "</span>"), 
                new BBTag("code", "<pre class=\"prettyprint\">", "</pre>"), 
                new BBTag("img", "<img src=\"${content}\" />", "", false, true), 
                new BBTag("quote", "<blockquote>", "</blockquote>"), 
                new BBTag("list", "<ul>", "</ul>"), 
                new BBTag("*", "<li>", "</li>", true, false),
                new BBTag("url", "<a href=\"${href}\">", "</a>", new BBAttribute("href", ""), new BBAttribute("href", "href")), 
                new BBTag("font", "<span style=\"font-family: ${tagattr}\">", "</span>", true, true, new BBAttribute("tagattr", ""), new BBAttribute("tagattr", "tagattr")), 
                new BBTag("color", "<span style=\"color: ${tagattr}\">", "</span>", true, true, new BBAttribute("tagattr", ""), new BBAttribute("tagattr", "tagattr")), 
                new BBTag("size", "<span style=\"size: ${tagattr}em\">", "</span>", true, true, new BBAttribute("tagattr", ""), new BBAttribute("tagattr", "tagattr")), 
                new BBTag("indent", "<span style=\"padding-left: ${tagattr}em\">", "</span>", true, true, new BBAttribute("tagattr", ""), new BBAttribute("tagattr", "tagattr")), 


            });

        String html = parser.ToHtml(bbcode
            .Replace("[list=1", "[list"))
            .Replace("\n", "<br>");

        webBrowser1.DocumentText = html;
}

wrote Feb 14, 2013 at 2:41 AM

wrote Mar 18, 2013 at 2:38 AM

Styles wrote Mar 18, 2013 at 2:38 AM

Ran into the same issue! Please patch it, I've fixed a local version... this doesn't seem to be updated though.

s0kol wrote Feb 5, 2014 at 9:38 AM

The fix to ParseAttributeValue doesn't allow for any other attributes than the default one. Here's a fix that does:
            var endIndex = input.IndexOfAny("=[]".ToCharArray(), end);
            
            if (input[endIndex] == '=')
            {
                endIndex = input.LastIndexOf(' ', end);
            }
that is a replacement for this line:
            var endIndex = input.IndexOfAny("[]".ToCharArray(), end);