CS Nuggets

This blog is for addons, bugs, fixes, and issues pertaining to Community Server.

CS: BUG FIX: BBCodes and Emoticons

As many of you may have noticed, there are some issues with the proper rendering of BBCodes and Emoticons.  This bug fix covers:

  1. Implementation of the missing [code] BBCode.
    1. A "file" attribute was added for specifying a file name.
  2. Implementation of a new [note] BBCode that works just like the [quote] BBCode, but does not display a header image.
    1. It has a "header" attribute to allow for bolded header text.
  3. Implmentation of a new [] BBCode that will mainly be used by developers.

CommunityServerComponents(20)/Components/Transforms.cs:

Change the following method which begins around line 44 from:

public static string FormatPostText(string rawPostBody, PostContentType postType, bool allowCustomTransforms)
{
    string formattedPost = rawPostBody;

    // because of the way we receive the post from MSHTML, somethings can already be encoded. This breaks the regex patterns
    // so we're unencoding anything that is already encoded so regex patterns work correctly. Later we'll encode everything again.

    //SCOTTW: Why? Encoded markup should stay encoded...otherwise it will not render
    //formattedPost = HttpUtility.HtmlDecode( formattedPost );

    if (allowCustomTransforms)
    {
        // must do emoteicons first because they are restricted from finding any inside [code][/code] blocks. We have to do
        // this before the later steps remove the [code][/code] blocks.
        if (CSContext.Current.SiteSettings.EnableEmoticons)
        {
            formattedPost = EmoticonTransforms(formattedPost);
        }
    }

    // convert any html inside code/pre blocks into encoded html
    formattedPost = EncodeCodeBlocks(formattedPost);

    // strip the html posts of any offending html tags and encode any that don't meet the criteria.
    formattedPost = HtmlScrubber.Clean(formattedPost, false, true);//  ScrubHtml( formattedPost, postType );

    // convert all html tags to bbcode as the bbcode processor will only allow safe attributes to be included in the ponst.
    //   formattedPost = HtmlToBBCode( formattedPost );

    // Remove any script code
    //
    //   formattedPost = Transforms.StripScriptTags(formattedPost);

    // Peform specialized transforms first.
    //

    // Do BBCode transform, if any
    //
    formattedPost = BBcodeToHtml(formattedPost);

    // Perform HTML Encoding of any tag elements, if not PostType.HTML
    //
    if (postType != PostContentType.HTML)
    { //} && postType != PostContentType.Poll) {
        formattedPost = HttpUtility.HtmlEncode(formattedPost);
        formattedPost = formattedPost.Replace("\n", Globals.HtmlNewLine);

        // Fix to reverse certain items that were HtmlEncoded above
        //
        formattedPost = UnHtmlEncode(formattedPost);
    }

    return formattedPost;
}

to:

public static string FormatPostText(string rawPostBody, PostContentType postType, bool allowCustomTransforms)
{
    string formattedPost = rawPostBody;

    // because of the way we receive the post from MSHTML, somethings can already be encoded. This breaks the regex patterns
    // so we're unencoding anything that is already encoded so regex patterns work correctly. Later we'll encode everything again.

    //SCOTTW: Why? Encoded markup should stay encoded...otherwise it will not render
    //formattedPost = HttpUtility.HtmlDecode( formattedPost );

    // convert any html inside code/pre blocks into encoded html
    formattedPost = EncodeCodeBlocks(formattedPost);

    // strip the html posts of any offending html tags and encode any that don't meet the criteria.
    formattedPost = HtmlScrubber.Clean(formattedPost, false, true);//  ScrubHtml( formattedPost, postType );

    // convert all html tags to bbcode as the bbcode processor will only allow safe attributes to be included in the ponst.
    //   formattedPost = HtmlToBBCode( formattedPost );

    // Remove any script code
    //
    //   formattedPost = Transforms.StripScriptTags(formattedPost);

    // Peform specialized transforms first.
    //

    // Do BBCode transform, if any
    //
    formattedPost = BBcodeToHtml(formattedPost);

    if (allowCustomTransforms)
    {
        // must do emoteicons first because they are restricted from finding any inside [code][/code] blocks. We have to do
        // this before the later steps remove the [code][/code] blocks.
        if (CSContext.Current.SiteSettings.EnableEmoticons)
        {
            formattedPost = EmoticonTransforms(formattedPost);
        }
    }

    // Perform HTML Encoding of any tag elements, if not PostType.HTML
    //
    if (postType != PostContentType.HTML)
    { //} && postType != PostContentType.Poll) {
        formattedPost = HttpUtility.HtmlEncode(formattedPost);
        formattedPost = formattedPost.Replace("\n", Globals.HtmlNewLine);

        // Fix to reverse certain items that were HtmlEncoded above
        //
        formattedPost = UnHtmlEncode(formattedPost);
    }

    return formattedPost;
}

Change the following method which begins around line 164 from:

// *********************************************************************
//  BBDecode
//
/// <summary>
/// Transforms a BBCode encoded string in appropriate HTML
/// </summary>
///
// ********************************************************************/
public static string BBcodeToHtml(string encodedString)
{
    // TDD TODO this shouldn't be hard coded, should be in a style sheet
    //

    // Used for normal quoting with a "<pic> <username> wrote:" prefix.
    //
    string quoteStartHtml = "";
    string quoteEndHtml = "</div></BLOCKQUOTE>";
    //quoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"txt4\"><img src=\"" + Globals.GetSkinPath() +"/images/icon-quote.gif" + "\">&nbsp;<strong>$1 wrote:</strong></td></tr><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">$3</td></tr></table></td></tr></table></BLOCKQUOTE>";

    // Used for when a username is not supplied.
    //
    string emptyquoteStartHtml = "<BLOCKQUOTE><div>";
    string emptyquoteEndHtml = "</div></BLOCKQUOTE>";
    //string emptyquoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">$2</td></tr></table></td></tr></table></BLOCKQUOTE>";

    // When using the Importer, we do not have a skin path.  We hardcode it here to
    // the default path.
    //
    if (Globals.GetSkinPath() == "")
        quoteStartHtml = "<BLOCKQUOTE><div><img src=\"themes/default/images/icon-quote.gif" + "\"> <strong>$1:</strong></div><div>";
    else
        quoteStartHtml = "<BLOCKQUOTE><div><img src=\"" + Globals.GetSkinPath() + "/images/icon-quote.gif" + "\"> <strong>$1:</strong></div><div>";

    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;

    // Bold, Italic, Underline
    //
    encodedString = Regex.Replace(encodedString, @"\[b(?:\s*)\]((.|\n)*?)\[/b(?:\s*)\]", "<b>$1</b>", options);
    encodedString = Regex.Replace(encodedString, @"\[i(?:\s*)\]((.|\n)*?)\[/i(?:\s*)\]", "<i>$1</i>", options);
    encodedString = Regex.Replace(encodedString, @"\[u(?:\s*)\]((.|\n)*?)\[/u(?:\s*)\]", "<u>$1</u>", options);

    // Left, Right, Center
    encodedString = Regex.Replace(encodedString, @"\[left(?:\s*)\]((.|\n)*?)\[/left(?:\s*)]", "<div style=\"text-align:left\">$1</div>", options);
    encodedString = Regex.Replace(encodedString, @"\[center(?:\s*)\]((.|\n)*?)\[/center(?:\s*)]", "<div style=\"text-align:center\">$1</div>", options);
    encodedString = Regex.Replace(encodedString, @"\[right(?:\s*)\]((.|\n)*?)\[/right(?:\s*)]", "<div style=\"text-align:right\">$1</div>", options);

    // Quote
    //
    //encodedString = Regex.Replace(encodedString, "\\[quote(?:\\s*)user=\"((.|\n)*?)\"\\]((.|\n)*?)\\[/quote(\\s*)\\]", quote, options);
    //encodedString = Regex.Replace(encodedString, "\\[quote(\\s*)\\]((.|\n)*?)\\[/quote(\\s*)\\]", emptyquote, options);
    encodedString = Regex.Replace(encodedString, "\\[quote(?:\\s*)user=(?:\"|&quot;|&#34;)(.*?)(?:\"|&quot;|&#34;)\\]", quoteStartHtml, options);
    encodedString = Regex.Replace(encodedString, "\\[/quote(\\s*)\\]", quoteEndHtml, options);
    encodedString = Regex.Replace(encodedString, "\\[quote(\\s*)\\]", emptyquoteStartHtml, options);
    encodedString = Regex.Replace(encodedString, "\\[/quote(\\s*)\\]", emptyquoteEndHtml, options);


    // Anchors
    //
    encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]www\.(.*?)\[/url(?:\s*)\]", "<a href=\"http://www.$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url=(?:""|&quot;|&#34;)((.|\n)*?)(?:\s*)(?:""|&quot;|&#34;)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[link(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[link=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);

    // Image
    //
    encodedString = Regex.Replace(encodedString, @"\[img(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img src=\"$1\" border=\"0\" />", options);
    encodedString = Regex.Replace(encodedString, @"\[img=((.|\n)*?)x((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img width=\"$1\" height=\"$3\" src=\"$5\" border=\"0\" />", options);

    // Color
    //
    encodedString = Regex.Replace(encodedString, @"\[color=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/color(?:\s*)\]", "<span style=\"color=$1;\">$3</span>", options);

    // Horizontal Rule
    //
    encodedString = Regex.Replace(encodedString, @"\[hr(?:\s*)\]", "<hr />", options);

    // Email
    //
    encodedString = Regex.Replace(encodedString, @"\[email(?:\s*)\]((.|\n)*?)\[/email(?:\s*)\]", "<a href=\"mailto:$1\">$1</a>", options);

    // Font size
    //
    encodedString = Regex.Replace(encodedString, @"\[size=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/size(?:\s*)\]", "<span style=\"font-size:$1\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[font=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/font(?:\s*)\]", "<span style=\"font-family:$1;\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[align=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/align(?:\s*)\]", "<div style=\"text-align:$1;\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[float=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/float(?:\s*)\]", "<div style=\"float:$1;\">$3</div>", options);

    string sListFormat = "<ol class=\"anf_list\" style=\"list-style:{0};\">$1</ol>";
    // Lists
    encodedString = Regex.Replace(encodedString, @"\[\*(?:\s*)]\s*([^\[*)", "<li>$1</li>", options);
    encodedString = Regex.Replace(encodedString, @"\[list(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", "<ul class=\"anf_list\">$1</ul>", options);
    encodedString = Regex.Replace(encodedString, @"\[list=1(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "decimal"), options);
    encodedString = Regex.Replace(encodedString, @"\[list=i(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "lower-roman"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=I(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "upper-roman"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=a(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "lower-alpha"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=A(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "upper-alpha"), RegexOptions.Compiled);

    return encodedString;
}

to:

// *********************************************************************
//  BBDecode
//
/// <summary>
/// Transforms a BBCode encoded string in appropriate HTML
/// </summary>
///
// ********************************************************************/
public static string BBcodeToHtml(string encodedString)
{
    // TDD TODO this shouldn't be hard coded, should be in a style sheet
    //

    // Used for normal quoting with a "<pic> <username> wrote:" prefix.
    //
    string skinPath;

    // When using the Importer, we do not have a skin path.  We hardcode it here to
    // the default path.
    //
    skinPath = Globals.GetSkinPath();

    if (skinPath == null || skinPath == string.Empty)
    {
        skinPath = Globals.ApplicationPath;

        if (skinPath.Equals("/"))
            skinPath = string.Empty;
    }

    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;

    // Bold, Italic, Underline
    //
    encodedString = Regex.Replace(encodedString, @"\[b(?:\s*)\]((.|\n)*?)\[/b(?:\s*)\]", "<b>$1</b>", options);
    encodedString = Regex.Replace(encodedString, @"\[i(?:\s*)\]((.|\n)*?)\[/i(?:\s*)\]", "<i>$1</i>", options);
    encodedString = Regex.Replace(encodedString, @"\[u(?:\s*)\]((.|\n)*?)\[/u(?:\s*)\]", "<u>$1</u>", options);

    // Left, Right, Center
    encodedString = Regex.Replace(encodedString, @"\[left(?:\s*)\]((.|\n)*?)\[/left(?:\s*)]", "<div style=\"text-align:left\">$1</div>", options);
    encodedString = Regex.Replace(encodedString, @"\[center(?:\s*)\]((.|\n)*?)\[/center(?:\s*)]", "<div style=\"text-align:center\">$1</div>", options);
    encodedString = Regex.Replace(encodedString, @"\[right(?:\s*)\]((.|\n)*?)\[/right(?:\s*)]", "<div style=\"text-align:right\">$1</div>", options);

    // Quote
    //
    encodedString = Regex.Replace(encodedString, @"\[quote(?:\s*)user=(?:""|&quot;|&#34;)(.*?)(?:""|&quot;|&#34;)\]", string.Format("<blockquote><div><img src=\"{0}/images/icon-quote.gif\">&nbsp;<strong>$1:</strong></div><br /><div>", skinPath), options);
    encodedString = Regex.Replace(encodedString, @"\[quote(\s*)\]", "<blockquote><div>", options);
    encodedString = Regex.Replace(encodedString, @"\[/quote(\s*)\]", "</div></blockquote>", options);

    // Note
    //
    encodedString = Regex.Replace(encodedString, @"\[note(?:\s*)header=(?:""|&quot;|&#34;)(.*?)(?:""|&quot;|&#34;)\]", "<blockquote><div><strong>$1:</strong></div><br /><div>", options);
    encodedString = Regex.Replace(encodedString, @"\[note(\s*)\]", "<blockquote><div>", options);
    encodedString = Regex.Replace(encodedString, @"\[/note(\s*)\]", "</div></blockquote>", options);

    // Code
    //
    encodedString = Regex.Replace(encodedString, @"\[code(?:\s*)file=(?:""|&quot;|&#34;)(.*?)(?:""|&quot;|&#34;)\]", "<blockquote style=\"overflow-x: scroll;\"><div><strong>$1:</strong></div><br /><pre style=\"margin: 0px;\">", options);
    encodedString = Regex.Replace(encodedString, @"\[code(?:\s*)\]", "<blockquote style=\"overflow-x: scroll;\"><pre style=\"margin: 0px;\">", options);
    encodedString = Regex.Replace(encodedString, @"\[/code(?:\s*)\]", "</pre></blockquote>", options);

    // Anchors
    //
    encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]www\.(.*?)\[/url(?:\s*)\]", "<a href=\"http://www.$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url=(?:""|&quot;|&#34;)((.|\n)*?)(?:\s*)(?:""|&quot;|&#34;)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[url=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[link(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options);
    encodedString = Regex.Replace(encodedString, @"\[link=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options);

    // Image
    //
    encodedString = Regex.Replace(encodedString, @"\[img(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img src=\"$1\" border=\"0\" />", options);
    encodedString = Regex.Replace(encodedString, @"\[img=((.|\n)*?)x((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img width=\"$1\" height=\"$3\" src=\"$5\" border=\"0\" />", options);

    // Color
    //
    encodedString = Regex.Replace(encodedString, @"\[color=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/color(?:\s*)\]", "<span style=\"color:$1;\">$3</span>", options);

    // Horizontal Rule
    //
    encodedString = Regex.Replace(encodedString, @"\[hr(?:\s*)\]", "<hr />", options);

    // Email
    //
    encodedString = Regex.Replace(encodedString, @"\[email(?:\s*)\]((.|\n)*?)\[/email(?:\s*)\]", "<a href=\"mailto:$1\">$1</a>", options);

    // Font size
    //
    encodedString = Regex.Replace(encodedString, @"\[size=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/size(?:\s*)\]", "<span style=\"font-size:$1\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[font=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/font(?:\s*)\]", "<span style=\"font-family:$1;\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[align=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/align(?:\s*)\]", "<div style=\"text-align:$1;\">$3</span>", options);
    encodedString = Regex.Replace(encodedString, @"\[float=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/float(?:\s*)\]", "<div style=\"float:$1;\">$3</div>", options);

    // Lists
    string sListFormat = "<ol class=\"anf_list\" style=\"list-style:{0};\">$1</ol>";
    encodedString = Regex.Replace(encodedString, @"\[\*(?:\s*)]\s*([^\[*)", "<li>$1</li>", options);
    encodedString = Regex.Replace(encodedString, @"\[list(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", "<ul class=\"anf_list\">$1</ul>", options);
    encodedString = Regex.Replace(encodedString, @"\[list=1(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "decimal"), options);
    encodedString = Regex.Replace(encodedString, @"\[list=i(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "lower-roman"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=I(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "upper-roman"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=a(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "lower-alpha"), RegexOptions.Compiled);
    encodedString = Regex.Replace(encodedString, @"\[list=A(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format(sListFormat, "upper-alpha"), RegexOptions.Compiled);

    // New code for developers
    encodedString = Regex.Replace(encodedString, @"\[\]", "[", options);

    return encodedString;
}

communityserver.config:

The final part of this bug fix requires a change in the order of lines in the <CSModules> section of your communityserver.config file.  To do this, find the following lines near the end of the file:

<add name = "AutoApproveForumModule" type="CommunityServer.Discussions.Components.AutoApproveForumModule, CommunityServer.Discussions" />
<add name = "BBcodeToHtml" type = "CommunityServer.Discussions.Components.BBcodeToHtmlModule, CommunityServer.Discussions" />
<add name = "IrcCommands" type = "CommunityServer.Discussions.Components.IrcCommandsModule, CommunityServer.Discussions" />
<add name = "ForumCensorship" type = "CommunityServer.Discussions.Components.CensorshipModule, CommunityServer.Discussions" />
<add name = "ForumEmoticon" type = "CommunityServer.Discussions.Components.EmoticonModule, CommunityServer.Discussions" />
<add name = "ForumSourceCode" type = "CommunityServer.Discussions.Components.SourceCodeModule, CommunityServer.Discussions" />
<add name = "ForumPlainText" type = "CommunityServer.Discussions.Components.PlainTextModule, CommunityServer.Discussions" />
<add name = "ForumHtmlScrubbing" type = "CommunityServer.Discussions.Components.HtmlScrubbingModule, CommunityServer.Discussions" />
<add name = "ForumCollapse" type = "CommunityServer.Discussions.Components.CollapseModule, CommunityServer.Discussions" />

and change the order to:

<add name = "AutoApproveForumModule" type="CommunityServer.Discussions.Components.AutoApproveForumModule, CommunityServer.Discussions" />
<add name = "IrcCommands" type = "CommunityServer.Discussions.Components.IrcCommandsModule, CommunityServer.Discussions" />
<add name = "ForumCensorship" type = "CommunityServer.Discussions.Components.CensorshipModule, CommunityServer.Discussions" />
<add name = "ForumSourceCode" type = "CommunityServer.Discussions.Components.SourceCodeModule, CommunityServer.Discussions" />
<add name = "ForumPlainText" type = "CommunityServer.Discussions.Components.PlainTextModule, CommunityServer.Discussions" />
<add name = "ForumHtmlScrubbing" type = "CommunityServer.Discussions.Components.HtmlScrubbingModule, CommunityServer.Discussions" />
<add name = "BBcodeToHtml" type = "CommunityServer.Discussions.Components.BBcodeToHtmlModule, CommunityServer.Discussions" />
<add name = "ForumEmoticon" type = "CommunityServer.Discussions.Components.EmoticonModule, CommunityServer.Discussions" />
<add name = "ForumCollapse" type = "CommunityServer.Discussions.Components.CollapseModule, CommunityServer.Discussions" />

 

To use the new code for developers, you just type a closing bracket immediately after the opening bracket.  For example, entering:

[]b]This is how you bold text[]/b]

in your post, will display:

[b]This is how you bold text[/b]

which in turn would display the following when used in a post:

This is how you bold text

If you have any questions or comments, please post them here.

Leave a Comment

(required) 

(required) 

(optional)

(required)