/// <summary> /// Applies Custom YafBBCode Rules from the YafBBCode table /// </summary> /// <param name="rulesEngine"> /// The rules Engine. /// </param> protected void AddCustomBBCodeRules(IProcessReplaceRules rulesEngine) { var bbcodeTable = this.Get <YafDbBroker>().GetCustomBBCode(); // handle custom bbcodes row by row... foreach (var codeRow in bbcodeTable.Where(codeRow => !(codeRow.UseModule ?? false) && codeRow.SearchRegex.IsSet())) { if (codeRow.Variables.IsSet()) { // handle variables... string[] variables = codeRow.Variables.Split(';'); var rule = new VariableRegexReplaceRule( codeRow.SearchRegex, codeRow.ReplaceRegex, _Options, variables) { RuleRank = 50 }; rulesEngine.AddRule(rule); } else { // just standard replace... var rule = new SimpleRegexReplaceRule(codeRow.SearchRegex, codeRow.ReplaceRegex, _Options) { RuleRank = 50 }; rulesEngine.AddRule(rule); } } }
/// <summary> /// Adds smiles replacement rules to the collection from the DB /// </summary> /// <param name="rules"> /// The rules. /// </param> public void AddSmiles([NotNull] IProcessReplaceRules rules) { CodeContracts.VerifyNotNull(rules, "rules"); var smiles = this.Get <YafDbBroker>().GetSmilies(); int codeOffset = 0; foreach (var smile in smiles) { string code = smile.Code; code = code.Replace("&", "&"); code = code.Replace(">", ">"); code = code.Replace("<", "<"); code = code.Replace("\"", """); // add new rules for smilies... var lowerRule = new SimpleReplaceRule( code.ToLower(), @"<img src=""{0}"" alt=""{1}"" />".FormatWith( YafBuildLink.Smiley(smile.Icon), HttpContext.Current.Server.HtmlEncode(smile.Emoticon))); var upperRule = new SimpleReplaceRule( code.ToUpper(), @"<img src=""{0}"" alt=""{1}"" />".FormatWith( YafBuildLink.Smiley(smile.Icon), HttpContext.Current.Server.HtmlEncode(smile.Emoticon))); // increase the rank as we go... lowerRule.RuleRank = lowerRule.RuleRank + 100 + codeOffset; upperRule.RuleRank = upperRule.RuleRank + 100 + codeOffset; rules.AddRule(lowerRule); rules.AddRule(upperRule); // add a bit more rank codeOffset++; } }
/// <summary> /// Creates the rules that convert HTML to <see cref="YafBBCode"/> /// </summary> /// <param name="ruleEngine"> /// The rule Engine. /// </param> /// <param name="doFormatting"> /// The do Formatting. /// </param> /// <param name="convertBBQuotes"> /// The convert BB Quotes. /// </param> public void CreateHtmlRules(IProcessReplaceRules ruleEngine, bool doFormatting, bool convertBBQuotes) { // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( @"<a.*?href=""mailto:(?<email>(.*?))"".*?>(?<inner>(.*?))</a>", "[email=${email}]${inner}[/email]", _Options, new[] { "email" })); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( @"<a.*?href=""(?<inner>(.*?))"".*?>(?<description>(.*?))</a>", "[url=${inner}]${description}[/url]", _Options, new[] { "description" })); // TODO : this.AddSmiles(ruleEngine); ruleEngine.AddRule( new VariableRegexReplaceRule( @"<img.*?src=""(?<inner>(.*?))"".*?alt=""(?<description>(.*?))"".*?/>", "[img=${inner}]${description}[/img]", _Options, new[] { "description" })); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule( @"<span style=""font-size: (?<size>([1-9]));"">(?<inner>(.*?))</span>", "[size=${size}]${inner}[/size]", _Options)); // font ruleEngine.AddRule( new VariableRegexReplaceRule( @"<span style=""font-family: (?<font>(.*?));"">(?<inner>(.*?))</span>", "[font=${font}]${inner}[/font]", _Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( @"<span style=""color: (?<color>(\#?[-a-z0-9]*));"">(?<inner>(.*?))</span>", "[color=${color}]${inner}[/color]", _Options, new[] { "color" })); // lists ruleEngine.AddRule( new SimpleRegexReplaceRule("<ul>(?<inner>(.*?))</ul>", "[list]${inner}[/list]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"1\">(?<inner>(.*?))</ol>", "[list=1]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule("<ol>(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:number\">(?<inner>(.*?))</ol>", "[list=1]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"a\">(?<inner>(.*?))</ol>", "[list=a]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"A\">(?<inner>(.*?))</ol>", "[list=A]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:lower-alpha\">(?<inner>(.*?))</ol>", "[list=a]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:upper-alpha\">(?<inner>(.*?))</ol>", "[list=A]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"i\">(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"I\">(?<inner>(.*?))</ol>", "[list=I]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:lower-roman\">(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:upper-roman\">(?<inner>(.*?))</ol>", "[list=I]${inner}[/list]", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule("<li>", "[*]", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"center\">(?<inner>(.*?))</div>", "[center]${inner}[/center]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"left\">(?<inner>(.*?))</div>", "[left]${inner}[/left]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"right\">(?<inner>(.*?))</div>", "[right]${inner}[/right]", _Options)); // Indent text ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div style=\"margin-left:40px\">(?<inner>(.*?))</div>", "[indent]${inner}[/indent]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<b>", "[b]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</b>", "[/b]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<strong>", "[b]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</strong>", "[/b]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<s>", "[s]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</s>", "[/s]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<em>", "[i]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</em>", "[/i]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<u>", "[u]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</u>", "[/u]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"<span style=""text-decoration: underline;"">(?<inner>(.*?))</span>", "[u]${inner}[/u]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"<span class=""highlight"">(?<inner>(.*?))</span>", "[h]${inner}[/h]", _Options)); // CODE Tags ruleEngine.AddRule( new VariableRegexReplaceRule( @"<div class=""code"">.*?<div class=""innercode"">.*?<pre class=""brush:(?<language>(.*?));"">(?<inner>(.*?))</pre>.*?</div>", "[code=${language}]${inner}[/code]", _Options, new[] { "language" })); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div class=\"code\">.*?<div class=\"innercode\">(?<inner>(.*?))</div>", "[code]${inner}[/code]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<br />", "\r\n", _Options)); // Remove remaining tags. ruleEngine.AddRule(new SingleRegexReplaceRule("<p>", string.Empty, _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</p>", string.Empty, _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule(" ", string.Empty, _Options)); // remove remaining tags ruleEngine.AddRule(new SingleRegexReplaceRule("<[^>]+>", string.Empty, _Options) { RuleRank = 100 }); }
/// <summary> /// Creates the rules that convert <see cref="YafBBCode"/> to HTML /// </summary> /// <param name="ruleEngine"> /// The rule Engine. /// </param> /// <param name="doFormatting"> /// The do Formatting. /// </param> /// <param name="targetBlankOverride"> /// The target Blank Override. /// </param> /// <param name="useNoFollow"> /// The use No Follow. /// </param> /// <param name="convertBBQuotes"> /// The convert BB Quotes. /// </param> public void CreateBBCodeRules( IProcessReplaceRules ruleEngine, bool doFormatting, bool targetBlankOverride, bool useNoFollow, bool convertBBQuotes) { string target = (this.Get<YafBoardSettings>().BlankLinks || targetBlankOverride) ? "target=\"_blank\"" : string.Empty; string nofollow = useNoFollow ? "rel=\"nofollow\"" : string.Empty; const string ClassModal = "class=\"ceebox\""; // pull localized strings string localQuoteStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_QUOTE"); string localCodeStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_CODE"); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule(_RgxSize, @"<span style=""font-size:${size}"">${inner}</span>", _Options)); if (doFormatting) { ruleEngine.AddRule( new CodeRegexReplaceRule( _rgxNoParse, @"${inner}")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxBold, "<strong>${inner}</strong>")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxStrike, "<s>${inner}</s>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxItalic, "<em>${inner}</em>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxUnderline, "<u>${inner}</u>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxHighlighted, @"<span class=""highlight"">${inner}</span>", _Options)); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxEmail2, "<a href=\"mailto:${email}\">${inner}</a>", new[] { "email" })); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxEmail1, @"<a href=""mailto:${inner}"">${inner}</a>")); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl2, "<a {0} {1} href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target).Replace("{1}", nofollow), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl1, "<a {0} {1} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl2, "<a {0} {1} {2} href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl1, "<a {0} {1} {2} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // font ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxFont, "<span style=\"font-family:${font}\">${inner}</span>", _Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxColor, "<span style=\"color:${color}\">${inner}</span>", _Options, new[] { "color" })); // lists ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxList1, "<ul>${inner}</ul>", _Options)); /*ruleEngine.AddRule( new VariableRegexReplaceRule(_rgxList2, "<ol type=\"${type}\">${inner}</ol>", _options, new[] { "type" }));*/ ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListNumber, "<ol style=\"list-style-type:number\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerRoman, "<ol style=\"list-style-type:lower-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperRoman, "<ol style=\"list-style-type:upper-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerAlpha, "<ol style=\"list-style-type:lower-alpha\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperAlpha, "<ol style=\"list-style-type:upper-alpha\">${inner}</ol>", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule(_RgxBullet, "<li>", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxCenter, "<div align=\"center\">${inner}</div>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxLeft, "<div align=\"left\">${inner}</div>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxRight, "<div align=\"right\">${inner}</div>", _Options)); // indent ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxIndent, "<div style=\"margin-left:40px\">${inner}</div>", _Options)); // add max-width and max-height to posted Image var maxWidth = this.Get<YafBoardSettings>().ImageAttachmentResizeWidth; var maxHeight = this.Get<YafBoardSettings>().ImageAttachmentResizeHeight; string styleAttribute = this.Get<YafBoardSettings>().ResizePostedImages ? " style=\"max-width:{0}px;max-height:{1}px\"".FormatWith( maxWidth, maxHeight) : string.Empty; // image ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImg, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"UserPostedImage\"{0} />".Replace( "{0}", styleAttribute), new[] { "http" }, new[] { "http://" }) { RuleRank = 70 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgEmptyTitle, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"UserPostedImage\"{0} />".Replace( "{0}", styleAttribute), new[] { "http" }, new[] { "http://" }) { RuleRank = 71 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgTitle, "<img src=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" class=\"UserPostedImage\"{0} />" .Replace("{0}", styleAttribute), new[] { "http", "description" }, new[] { "http://", string.Empty }) { RuleRank = 72 }); // basic hr and br rules var hrRule = new SingleRegexReplaceRule( _RgxHr, "<hr />", RegexOptions.IgnoreCase | RegexOptions.Multiline); // Multiline, since ^ must match beginning of line var brRule = new SingleRegexReplaceRule( _RgxBr, "<br />", RegexOptions.IgnoreCase | RegexOptions.Multiline) { RuleRank = hrRule.RuleRank + 1 }; // Ensure the newline rule is processed after the HR rule, otherwise the newline characters in the HR regex will never match ruleEngine.AddRule(hrRule); ruleEngine.AddRule(brRule); } // add smilies this.AddSmiles(ruleEngine); if (convertBBQuotes) { // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _regexCodeWithLanguage, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr)) { RuleRank = 40 }); // handle custom YafBBCode this.AddCustomBBCodeRules(ruleEngine); // add rule for code block type with no syntax highlighting ruleEngine.AddRule( new CodeRegexReplaceRule( _rgxCode1, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr))); ruleEngine.AddRule( new QuoteRegexReplaceRule( OpenQuoteUserIdRegex, @"<div class=""quote""><span class=""quotetitle"">${quote}</span><div class=""innerquote"">", _Options)); // simple open quote tag var simpleOpenQuoteReplace = @"<div class=""quote""><span class=""quotetitle"">{0}</span><div class=""innerquote"">" .FormatWith(localQuoteStr); ruleEngine.AddRule( new SimpleRegexReplaceRule(OpenQuoteRegex, simpleOpenQuoteReplace, _Options) { RuleRank = 62 }); // and finally the closing quote tag ruleEngine.AddRule( new SingleRegexReplaceRule(CloseQuoteRegex, "</div></div>", _Options) { RuleRank = 63 }); } // post and topic rules... ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxPost, @"<a href=""${post}"" title=""${inner}"">${inner}</a>", _Options)); ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxTopic, @"<a href=""${topic}"" title=""${inner}"">${inner}</a>", _Options)); }
/// <summary> /// Applies Custom YafBBCode Rules from the YafBBCode table /// </summary> /// <param name="rulesEngine"> /// The rules Engine. /// </param> protected void AddCustomBBCodeRules(IProcessReplaceRules rulesEngine) { var bbcodeTable = this.Get<YafDbBroker>().GetCustomBBCode(); // handle custom bbcodes row by row... foreach (var codeRow in bbcodeTable.Where<BBCode>(codeRow => !(codeRow.UseModule ?? false) && StringExtensions.IsSet(codeRow.SearchRegex))) { if (codeRow.Variables.IsSet()) { // handle variables... string[] variables = codeRow.Variables.Split(new[] { ';' }); var rule = new VariableRegexReplaceRule( codeRow.SearchRegex, codeRow.ReplaceRegex, _Options, variables) { RuleRank = 50 }; rulesEngine.AddRule(rule); } else { // just standard replace... var rule = new SimpleRegexReplaceRule(codeRow.SearchRegex, codeRow.ReplaceRegex, _Options) { RuleRank = 50 }; rulesEngine.AddRule(rule); } } }
/// <summary> /// Creates the rules that convert <see cref="YafBBCode"/> to HTML /// </summary> /// <param name="ruleEngine"> /// The rule Engine. /// </param> /// <param name="doFormatting"> /// The do Formatting. /// </param> /// <param name="targetBlankOverride"> /// The target Blank Override. /// </param> /// <param name="useNoFollow"> /// The use No Follow. /// </param> /// <param name="convertBBQuotes"> /// The convert BB Quotes. /// </param> public void CreateBBCodeRules( IProcessReplaceRules ruleEngine, bool doFormatting, bool targetBlankOverride, bool useNoFollow, bool convertBBQuotes) { string target = (this.Get<YafBoardSettings>().BlankLinks || targetBlankOverride) ? "target=\"_blank\"" : string.Empty; string nofollow = useNoFollow ? "rel=\"nofollow\"" : string.Empty; const string ClassModal = "class=\"ceebox\""; // pull localized strings string localQuoteStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_QUOTE"); string localQuoteWroteStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_QUOTEWROTE"); string localQuotePostedStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_QUOTEPOSTED"); string localCodeStr = this.Get<ILocalization>().GetText("COMMON", "BBCODE_CODE"); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule(_RgxSize, @"<span style=""font-size:${size}"">${inner}</span>", _Options)); if (doFormatting) { ruleEngine.AddRule( new CodeRegexReplaceRule( _rgxNoParse, @"${inner}")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxBold, "<b>${inner}</b>")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxStrike, "<s>${inner}</s>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxItalic, "<em>${inner}</em>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxUnderline, "<u>${inner}</u>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxHighlighted, @"<span class=""highlight"">${inner}</span>", _Options)); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxEmail2, "<a href=\"mailto:${email}\">${inner}</a>", new[] { "email" })); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxEmail1, @"<a href=""mailto:${inner}"">${inner}</a>")); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl2, "<a {0} {1} href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target).Replace("{1}", nofollow), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl1, "<a {0} {1} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl2, "<a {0} {1} {2} href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl1, "<a {0} {1} {2} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // font ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxFont, "<span style=\"font-family:${font}\">${inner}</span>", _Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxColor, "<span style=\"color:${color}\">${inner}</span>", _Options, new[] { "color" })); // lists ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxList1, "<ul>${inner}</ul>", _Options)); /*ruleEngine.AddRule( new VariableRegexReplaceRule(_rgxList2, "<ol type=\"${type}\">${inner}</ol>", _options, new[] { "type" }));*/ ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListNumber, "<ol style=\"list-style-type:number\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerRoman, "<ol style=\"list-style-type:lower-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperRoman, "<ol style=\"list-style-type:upper-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerAlpha, "<ol style=\"list-style-type:lower-alpha\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperAlpha, "<ol style=\"list-style-type:upper-alpha\">${inner}</ol>", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule(_RgxBullet, "<li>", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxCenter, "<div align=\"center\">${inner}</div>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxLeft, "<div align=\"left\">${inner}</div>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxRight, "<div align=\"right\">${inner}</div>", _Options)); // TODO add max-width and max-height /* var maxWidth = this.Get<YafBoardSettings>().ImageAttachmentResizeWidth; var maxHeight = this.Get<YafBoardSettings>().ImageAttachmentResizeHeight; string styleAttribute = "style=\"max-width:{0}px;max-height:{1}px\"".FormatWith(maxWidth, maxHeight);*/ // image ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImg, "<img src=\"${http}${inner}\" alt=\"\" class=\"UserPostedImage\"/>", new[] { "http" }, new[] { "http://" }) { RuleRank = 70 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgEmptyTitle, "<img src=\"${http}${inner}\" alt=\"\" class=\"UserPostedImage\"/>", new[] { "http" }, new[] { "http://" }) { RuleRank = 71 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgTitle, "<img src=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" class=\"UserPostedImage\" />", new[] { "http", "description" }, new[] { "http://", string.Empty }) { RuleRank = 72 }); // tha_watcha : Easy Quote Disabled http://forum.yetanotherforum.net/yaf_postst13495_Addition-of-Easy-Quote-RegEx-in-Revision-4906.aspx // Looks like it doesnt work as expected should be correctly implemented or else removed. // // add easy quoting... /*var easyQuoteRule = new SimpleRegexReplaceRule( _RgxEasyQuote, @" <span class=""easyquote"">${inner}</span>", RegexOptions.IgnoreCase | RegexOptions.Multiline);*/ // basic hr and br rules var hrRule = new SingleRegexReplaceRule( _RgxHr, "<hr />", RegexOptions.IgnoreCase | RegexOptions.Multiline); // Multiline, since ^ must match beginning of line var brRule = new SingleRegexReplaceRule( _RgxBr, "<br />", RegexOptions.IgnoreCase | RegexOptions.Multiline) { RuleRank = hrRule.RuleRank + 1 }; // Ensure the newline rule is processed after the HR rule, otherwise the newline characters in the HR regex will never match //ruleEngine.AddRule(easyQuoteRule); ruleEngine.AddRule(hrRule); ruleEngine.AddRule(brRule); } // add smilies this.AddSmiles(ruleEngine); if (convertBBQuotes) { // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _regexCodeWithLanguage, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr)) { RuleRank = 41 }); // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _regexCodeWithLanguage2, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr)) { RuleRank = 40 }); // handle custom YafBBCode this.AddCustomBBCodeRules(ruleEngine); // add rule for code block type with no syntax highlighting ruleEngine.AddRule( new CodeRegexReplaceRule( _rgxCode1, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr))); // "quote" handling... string tmpReplaceStr3 = @"<div class=""quote""><span class=""quotetitle"">{0} <a href=""{1}""><img src=""{2}"" title=""{3}"" alt=""{3}"" /></a></span><div class=""innerquote"">{4}</div></div>" .FormatWith( localQuotePostedStr.Replace("{0}", "${quote}"), YafBuildLink.GetLink(ForumPages.posts, "m={0}#post{0}", "${id}"), this.Get<ITheme>().GetItem("ICONS", "ICON_LATEST"), this.Get<ILocalization>().GetText("COMMON", "BBCODE_QUOTEPOSTED_TT"), "${inner}"); ruleEngine.AddRule(new VariableRegexReplaceRule(_rgxQuote3, tmpReplaceStr3, new[] { "quote", "id" }) { RuleRank = 60 }); string tmpReplaceStr2 = @"<div class=""quote""><span class=""quotetitle"">{0}</span><div class=""innerquote"">{1}</div></div>" .FormatWith(localQuoteWroteStr.Replace("{0}", "${quote}"), "${inner}"); ruleEngine.AddRule(new VariableRegexReplaceRule(_rgxQuote2, tmpReplaceStr2, new[] { "quote" }) { RuleRank = 61 }); string tmpReplaceStr1 = @"<div class=""quote""><span class=""quotetitle"">{0}</span><div class=""innerquote"">{1}</div></div>" .FormatWith(localQuoteStr, "${inner}"); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxQuote1, tmpReplaceStr1) { RuleRank = 62 }); } // post and topic rules... ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxPost, @"<a {0} href=""${post}"" title=""${inner}"">${inner}</a>".Replace("{0}", target), _Options)); ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxTopic, @"<a {0} href=""${topic}"" title=""${inner}"">${inner}</a>".Replace("{0}", target), _Options)); }
/// <summary> /// Creates the rules that convert HTML to <see cref="YafBBCode"/> /// </summary> /// <param name="ruleEngine"> /// The rule Engine. /// </param> public void CreateHtmlRules(IProcessReplaceRules ruleEngine) { // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"center\">(?<inner>(.*?))</div>", "[center]${inner}[/center]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"left\">(?<inner>(.*?))</div>", "[left]${inner}[/left]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"right\">(?<inner>(.*?))</div>", "[right]${inner}[/right]", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: center;\">(?<inner>(.*?))</p>", "[center]${inner}[/center]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: left;\">(?<inner>(.*?))</p>", "[left]${inner}[/left]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: right;\">(?<inner>(.*?))</p>", "[right]${inner}[/right]", _Options)); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new VariableRegexReplaceRule( @"<span style=""font-size:(?<size>(.*?))px;"">(?<inner>(.*?))</span>", "[size=${size}]${inner}[/size]", _Options, new[] { "size" }) { RuleRank = 10 }); // font ruleEngine.AddRule( new VariableRegexReplaceRule( @"<span style=""font-family: (?<font>(.*?));"">(?<inner>(.*?))</span>", "[font=${font}]${inner}[/font]", _Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( @"<span style=""color: (?<color>(\#?[-a-z0-9]*));"">(?<inner>(.*?))</span>", "[color=${color}]${inner}[/color]", _Options, new[] { "color" })); // lists ruleEngine.AddRule( new SimpleRegexReplaceRule("<ul>(?<inner>(.*?))</ul>", "[list]${inner}[/list]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"1\">(?<inner>(.*?))</ol>", "[list=1]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule("<ol>(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:number\">(?<inner>(.*?))</ol>", "[list=1]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"a\">(?<inner>(.*?))</ol>", "[list=a]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"A\">(?<inner>(.*?))</ol>", "[list=A]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:lower-alpha\">(?<inner>(.*?))</ol>", "[list=a]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:upper-alpha\">(?<inner>(.*?))</ol>", "[list=A]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"i\">(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol type=\"I\">(?<inner>(.*?))</ol>", "[list=I]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:lower-roman\">(?<inner>(.*?))</ol>", "[list=i]${inner}[/list]", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<ol style=\"list-style-type:upper-roman\">(?<inner>(.*?))</ol>", "[list=I]${inner}[/list]", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule("<li>", "[*]", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"center\">(?<inner>(.*?))</div>", "[center]${inner}[/center]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"left\">(?<inner>(.*?))</div>", "[left]${inner}[/left]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div align=\"right\">(?<inner>(.*?))</div>", "[right]${inner}[/right]", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: center;\">(?<inner>(.*?))</p>", "[center]${inner}[/center]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: left;\">(?<inner>(.*?))</p>", "[left]${inner}[/left]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<p style=\"text-align: right;\">(?<inner>(.*?))</p>", "[right]${inner}[/right]", _Options)); // Indent text ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div style=\"margin-left:40px\">(?<inner>(.*?))</div>", "[indent]${inner}[/indent]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<b>", "[b]", _Options) { RuleRank = 4 }); ruleEngine.AddRule(new SingleRegexReplaceRule("</b>", "[/b]", _Options) { RuleRank = 5 }); ruleEngine.AddRule(new SingleRegexReplaceRule("<strong>", "[b]", _Options) { RuleRank = 3 }); ruleEngine.AddRule(new SingleRegexReplaceRule("</strong>", "[/b]", _Options) { RuleRank = 4 }); ruleEngine.AddRule(new SingleRegexReplaceRule("<s>", "[s]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</s>", "[/s]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<em>", "[i]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</em>", "[/i]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("<u>", "[u]", _Options)); ruleEngine.AddRule(new SingleRegexReplaceRule("</u>", "[/u]", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"<span style=""text-decoration: underline;"">(?<inner>(.*?))</span>", "[u]${inner}[/u]", _Options)); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( @"<a.*?href=""(?<inner>(.*?))"".*?>(?<description>(.*?))</a>", "[url=${inner}]${description}[/url]", _Options, new[] { "description" }) { RuleRank = 2 }); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( @"<a.*?href=""mailto:(?<email>(.*?))"".*?>(?<inner>(.*?))</a>", "[email=${email}]${inner}[/email]", _Options, new[] { "email" }) { RuleRank = 1 }); // TODO : this.AddSmiles(ruleEngine); ruleEngine.AddRule( new VariableRegexReplaceRule( @"<img.*?src=""(?<inner>(.*?))"".*?alt=""(?<description>(.*?))"".*?/>", "[img=${inner}]${description}[/img]", _Options, new[] { "description" })); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"<span class=""highlight"">(?<inner>(.*?))</span>", "[h]${inner}[/h]", _Options)); // CODE Tags ruleEngine.AddRule( new VariableRegexReplaceRule( @"<div class=""code"">.*?<div class=""innercode"">.*?<pre class=""brush:(?<language>(.*?));"">(?<inner>(.*?))</pre>.*?</div>", "[code=${language}]${inner}[/code]", _Options, new[] { "language" }) { RuleRank = 97 }); ruleEngine.AddRule( new SimpleRegexReplaceRule( "<div class=\"code\">.*?<div class=\"innercode\">(?<inner>(.*?))</div>", "[code]${inner}[/code]", _Options) { RuleRank = 98 }); ruleEngine.AddRule(new SimpleRegexReplaceRule("<br />", "\r\n", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule("<br>", "\r\n", _Options)); // Format paragraphs ruleEngine.AddRule(new SimpleRegexReplaceRule("<p>", "\r\n\r\n", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule("</p>", "[br]", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(" ", string.Empty, _Options)); // remove remaining tags ruleEngine.AddRule(new SimpleRegexReplaceRule("<[^>]+>", string.Empty, _Options) { RuleRank = 100 }); }
/// <summary> /// Creates the rules that convert <see cref="YafBBCode" /> to HTML /// </summary> /// <param name="ruleEngine">The rule Engine.</param> /// <param name="isHtml">if set to <c>true</c> [is HTML].</param> /// <param name="doFormatting">The do Formatting.</param> /// <param name="targetBlankOverride">The target Blank Override.</param> /// <param name="useNoFollow">The use No Follow.</param> /// <param name="convertBBQuotes">The convert BB Quotes.</param> public void CreateBBCodeRules( IProcessReplaceRules ruleEngine, bool isHtml, bool doFormatting, bool targetBlankOverride, bool useNoFollow, bool convertBBQuotes) { string target = (this.Get <YafBoardSettings>().BlankLinks || targetBlankOverride) ? "target=\"_blank\"" : string.Empty; string nofollow = useNoFollow ? "rel=\"nofollow\"" : string.Empty; const string ClassModal = ""; // pull localized strings string localQuoteStr = this.Get <ILocalization>().GetText("COMMON", "BBCODE_QUOTE"); string localCodeStr = this.Get <ILocalization>().GetText("COMMON", "BBCODE_CODE"); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule( @"\[size=(?<size>(.*?))\](?<inner>(.*?))\[/size\]", @"<span style=""font-size:${size}"">${inner}</span>", _Options)); if (doFormatting) { ruleEngine.AddRule( new CodeRegexReplaceRule( _rgxNoParse, @"${inner}")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxBold, "<strong>${inner}</strong>")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxStrike, "<s>${inner}</s>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxItalic, "<em>${inner}</em>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxUnderline, "<u>${inner}</u>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxHighlighted, @"<span class=""highlight"">${inner}</span>", _Options)); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxEmail2, "<a href=\"mailto:${email}\">${inner}</a>", new[] { "email" })); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxEmail1, @"<a href=""mailto:${inner}"">${inner}</a>")); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl2, "<a {0} {1} href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target) .Replace("{1}", nofollow), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" }) { RuleRank = 10 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl1, "<a {0} {1} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50) { RuleRank = 11 }); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl2, "<a {0} {1} {2} href=\"#\" data-href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl1, "<a {0} {1} {2} href=\"#\" data-href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>".Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", ClassModal), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // font ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxFont, "<span style=\"font-family:${font}\">${inner}</span>", _Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxColor, "<span style=\"color:${color}\">${inner}</span>", _Options, new[] { "color" })); // lists ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxList1, "<ul>${inner}</ul>", _Options)); /*ruleEngine.AddRule( * new VariableRegexReplaceRule(_rgxList2, "<ol type=\"${type}\">${inner}</ol>", _options, new[] { "type" }));*/ ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListNumber, "<ol style=\"list-style-type:number\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerRoman, "<ol style=\"list-style-type:lower-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperRoman, "<ol style=\"list-style-type:upper-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListLowerAlpha, "<ol style=\"list-style-type:lower-alpha\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxListUpperAlpha, "<ol style=\"list-style-type:upper-alpha\">${inner}</ol>", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule(_RgxBullet, "<li>", _Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxCenter, "<div align=\"center\">${inner}</div>", _Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxLeft, "<div align=\"left\">${inner}</div>", _Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxRight, "<div align=\"right\">${inner}</div>", _Options)); // indent ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxIndent, "<div style=\"margin-left:40px\">${inner}</div>", _Options)); // add max-width and max-height to posted Image var maxWidth = this.Get <YafBoardSettings>().ImageAttachmentResizeWidth; var maxHeight = this.Get <YafBoardSettings>().ImageAttachmentResizeHeight; string styleAttribute = this.Get <YafBoardSettings>().ResizePostedImages ? " style=\"max-width:{0}px;max-height:{1}px\"".FormatWith( maxWidth, maxHeight) : string.Empty; // image ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImg, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"UserPostedImage\"{0} />".Replace( "{0}", styleAttribute), new[] { "http" }, new[] { "http://" }) { RuleRank = 70 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgEmptyTitle, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"UserPostedImage\"{0} />".Replace( "{0}", styleAttribute), new[] { "http" }, new[] { "http://" }) { RuleRank = 71 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgTitle, "<img src=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" class=\"UserPostedImage\"{0} />" .Replace("{0}", styleAttribute), new[] { "http", "description" }, new[] { "http://", string.Empty }) { RuleRank = 72 }); // basic hr and br rules var hrRule = new SingleRegexReplaceRule( _RgxHr, "<hr />", RegexOptions.IgnoreCase | RegexOptions.Multiline); ruleEngine.AddRule( new SingleRegexReplaceRule(@"\[br\]", "</p>", _Options)); // Multiline, since ^ must match beginning of line var brRule = new SingleRegexReplaceRule( _RgxBr, "<br />", RegexOptions.IgnoreCase | RegexOptions.Multiline) { RuleRank = hrRule.RuleRank + 1 }; // Ensure the newline rule is processed after the HR rule, otherwise the newline characters in the HR regex will never match ruleEngine.AddRule(hrRule); if (!isHtml) { ruleEngine.AddRule(brRule); } else { // handle paragraphs ruleEngine.AddRule( new SingleRegexReplaceRule(@"\r\n", "<p>", _Options)); } } // add smilies this.AddSmiles(ruleEngine); if (convertBBQuotes) { // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _regexCodeWithLanguage, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr)) { RuleRank = 30 }); // handle custom YafBBCode this.AddCustomBBCodeRules(ruleEngine); // add rule for code block type with no syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _rgxCode1, @"<div class=""code""><strong>{0}</strong><div class=""innercode"">${inner}</div></div>".Replace("{0}", localCodeStr))); ruleEngine.AddRule( new QuoteRegexReplaceRule( OpenQuoteUserIdRegex, @"<div class=""quote""><span class=""quotetitle"">${quote}</span><div class=""innerquote"">", _Options)); // simple open quote tag var simpleOpenQuoteReplace = @"<div class=""quote""><span class=""quotetitle"">{0}</span><div class=""innerquote"">" .FormatWith(localQuoteStr); ruleEngine.AddRule( new SimpleRegexReplaceRule(OpenQuoteRegex, simpleOpenQuoteReplace, _Options) { RuleRank = 62 }); // and finally the closing quote tag ruleEngine.AddRule( new SingleRegexReplaceRule(CloseQuoteRegex, "</div></div>", _Options) { RuleRank = 63 }); } // post and topic rules... ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxPost, @"<a href=""${post}"" title=""${inner}"">${inner}</a>", _Options)); ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxTopic, @"<a href=""${topic}"" title=""${inner}"">${inner}</a>", _Options)); }
/// <summary> /// Creates the rules that convert <see cref="BBCode"/> to HTML /// </summary> /// <param name="messageId"> /// The message Id. /// </param> /// <param name="ruleEngine"> /// The rule Engine. /// </param> /// <param name="doFormatting"> /// The do Formatting. /// </param> /// <param name="targetBlankOverride"> /// The target Blank Override. /// </param> /// <param name="useNoFollow"> /// The use No Follow. /// </param> /// <param name="isEditMode"> /// Indicates if the formatting is for the Editor. /// </param> public void CreateBBCodeRules( [NotNull] int messageId, IProcessReplaceRules ruleEngine, bool doFormatting, bool targetBlankOverride, bool useNoFollow, bool isEditMode = false) { var target = this.Get <BoardSettings>().BlankLinks || targetBlankOverride ? "target=\"_blank\"" : string.Empty; var noFollow = useNoFollow ? "rel=\"nofollow\"" : string.Empty; // pull localized strings var localQuoteStr = this.Get <ILocalization>().GetText("COMMON", "BBCODE_QUOTE"); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule( @"\[size=(?<size>(.*?))\](?<inner>(.*?))\[/size\]", @"<span style=""font-size:${size}"">${inner}</span>", Options)); if (doFormatting) { ruleEngine.AddRule( new CodeRegexReplaceRule( new Regex(@"\[noparse\](?<inner>(.*?))\[/noparse\]", Options | RegexOptions.Compiled), @"${inner}")); ruleEngine.AddRule( new SimpleRegexReplaceRule( new Regex(@"\[B\](?<inner>(.*?))\[/B\]", Options | RegexOptions.Compiled), "<strong>${inner}</strong>")); ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[S\](?<inner>(.*?))\[/S\]", "<s>${inner}</s>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[I\](?<inner>(.*?))\[/I\]", "<em>${inner}</em>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[U\](?<inner>(.*?))\[/U\]", "<u>${inner}</u>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[h\](?<inner>(.*?))\[/h\]", "<mark>${inner}</mark>", Options)); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[email=(?<email>[^\]]*)\](?<inner>([^""\r\n\]\[]+?))\[/email\]", Options | RegexOptions.Compiled), "<a href=\"mailto:${email}\">${inner} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>", new[] { "email" })); ruleEngine.AddRule( new SimpleRegexReplaceRule( new Regex( @"\[email[^\]]*\](?<inner>([^""\r\n\]\[]+?))\[/email\]", Options | RegexOptions.Compiled), @"<a href=""mailto:${inner}"">${inner}</a>")); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[url\=(?<http>(skype:)|(http://)|(https://)|(ftp://)|(ftps://))?(?<url>([^javascript:])([^""\r\n\]\[]*?))\](?<inner>(.+?))\[/url\]", Options | RegexOptions.Compiled), "<a {0} {1} href=\"${http}${url}\" title=\"${http}${url}\">${inner} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", noFollow), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" }) { RuleRank = 10 }); ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[url\](?<http>(skype:)|(http://)|(https://)|(ftp://)|(ftps://)|(mailto:))?(?<inner>([^javascript:])(.+?))\[/url\]", Options | RegexOptions.Compiled), "<a {0} {1} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", noFollow), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50) { RuleRank = 11 }); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"(?<before>^|[ ]|\[[A-Za-z0-9]\]|\[\*\]|[A-Za-z0-9])(?<!"")(?<!href="")(?<!src="")(?<inner>(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled), "${before}<a {0} {1} href=\"${inner}\" title=\"${inner}\">${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", noFollow), new[] { "before" }, new[] { string.Empty }, 50) { RuleRank = 12 }); ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"(?<before>^|[ ]|\[[A-Za-z0-9]\]|\[\*\]|[A-Za-z0-9])(?<!href="")(?<!src="")(?<inner>(http://|https://|ftp://)(?:[\w-]+\.)+[\w-]+(?:/[\w-./?%&=+;,:#~/(/)$]*[^.<|^.\[])?)", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled), "${before}<a {0} {1} href=\"${inner}\" title=\"${inner}\">${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", noFollow), new[] { "before" }, new[] { string.Empty }, 50) { RuleRank = 13 }); // font ruleEngine.AddRule( new VariableRegexReplaceRule( @"\[font=(?<font>([-a-z0-9, ]*))\](?<inner>(.*?))\[/font\]", "<span style=\"font-family:${font}\">${inner}</span>", Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( @"\[color=(?<color>(\#?[-a-z0-9]*))\](?<inner>(.*?))\[/color\]", "<span style=\"color:${color}\">${inner}</span>", Options, new[] { "color" })); // lists ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[list\](?<inner>(.*?))\[/list\]", "<ul>${inner}</ul>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[list=1\](?<inner>(.*?))\[/list\]", "<ol style=\"list-style-type:number\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[list=i\](?<inner>(.*?))\[/list\]", "<ol style=\"list-style-type:lower-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[list=I\](?<inner>(.*?))\[/list\]", "<ol style=\"list-style-type:upper-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[list=a\](?<inner>(.*?))\[/list\]", "<ol style=\"list-style-type:lower-alpha\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[list=A\](?<inner>(.*?))\[/list\]", "<ol style=\"list-style-type:upper-alpha\">${inner}</ol>", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule(@"\[\*\]", "<li>", Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[center\](?<inner>(.*?))\[/center\]", "<div align=\"center\">${inner}</div>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[left\](?<inner>(.*?))\[/left\]", "<div align=\"left\">${inner}</div>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[right\](?<inner>(.*?))\[/right\]", "<div align=\"right\">${inner}</div>", Options)); // indent ruleEngine.AddRule( new SimpleRegexReplaceRule( @"\[indent\](?<inner>(.*?))\[/indent\]", "<div style=\"margin-left:40px\">${inner}</div>", Options)); string imageHtml; string imageHtmlWithDesc; if (messageId > 0) { imageHtml = "<a href=\"${http}${inner}\" data-gallery=\"#blueimp-gallery-" + messageId + "\"><img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"img-user-posted img-thumbnail\" style=\"max-height:${height}px;\"></a>"; imageHtmlWithDesc = "<a href=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" data-gallery=\"#blueimp-gallery-" + messageId + "\"><img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"img-user-posted img-thumbnail\" style=\"max-height:${height}px;\"></a>"; } else { imageHtml = "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"img-user-posted img-thumbnail\" style=\"max-height:${height}px;\">"; imageHtmlWithDesc = "<img src=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" class=\"img-user-posted img-thumbnail\" style=\"max-height:${height}px;\">"; } // image ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[img\](?<http>(http://)|(https://)|(ftp://)|(ftps://))?(?<inner>((?!.+logout)[^""\r\n\]\[]+?\.((googleusercontent[^\[]*)|(jpg[^\[]*)|(jpeg[^\[]*)|(bmp[^\[]*)|(png[^\[]*)|(gif[^\[]*)|(tif[^\[]*)|(ashx[^\[]*)|(php[^\[]*)|(aspx[^\[]*))))\[/img\]", Options | RegexOptions.Compiled), imageHtml, new[] { "http", "height" }, new[] { "http://", this.Get <BoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 70 }); ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[img=(?<http>(http://)|(https://)|(ftp://)|(ftps://))?(?<inner>((?!.+logout)[^""\r\n\]\[]+?\.((googleusercontent[^\[]*)|(jpg[^\]\[/img\]]*)|(jpeg[^\[\[/img\]]*)|(bmp[^\[\[/img\]]*)|(png[^\]\[/img\]]*)|(gif[^\]\[/img\]]*)|(tif[^\]\[/img\]]*)|(ashx[^\]\[/img\]]*)|(php[^\]\[/img\]]*)|(aspx[^\]\[/img\]]*))))\]\[/img\]", Options | RegexOptions.Compiled), imageHtml, new[] { "http", "height" }, new[] { "http://", this.Get <BoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 71 }); ruleEngine.AddRule( new VariableRegexReplaceRule( new Regex( @"\[img=(?<http>(http://)|(https://)|(ftp://)|(ftps://))?(?<inner>((?!.+logout)[^""\r\n\]\[]+?\.((googleusercontent[^\[]*)|(jpg[^\]]*)|(jpeg[^\]]*)|(bmp[^\]]*)|(png[^\]]*)|(gif[^\]]*)|(tif[^\]]*)|(ashx[^\]]*)|(php[^\]]*)|(aspx[^\]]*))))\](?<description>[^\[]*)\[/img\]", Options | RegexOptions.Compiled), imageHtmlWithDesc, new[] { "http", "description", "height" }, new[] { "http://", string.Empty, this.Get <BoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 72 }); // basic hr and br rules var horizontalLineRule = new SingleRegexReplaceRule( "^[-][-][-][-][-]*[\r]?[\n]", "<hr />", RegexOptions.IgnoreCase | RegexOptions.Multiline); ruleEngine.AddRule(new SingleRegexReplaceRule(@"\[br\]", "</p>", Options)); // Multiline, since ^ must match beginning of line var breakRule = new SingleRegexReplaceRule( "\r\n", "<br />", RegexOptions.IgnoreCase | RegexOptions.Multiline) { RuleRank = horizontalLineRule.RuleRank + 1 }; // Ensure the newline rule is processed after the HR rule, otherwise the newline characters in the HR regex will never match ruleEngine.AddRule(horizontalLineRule); ruleEngine.AddRule(isEditMode ? breakRule : new SingleRegexReplaceRule(@"\r\n", "<p>", Options)); } // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlighterRegexReplaceRule( isEditMode, new Regex(@"\[code=(?<language>[^\]]*)\](?<inner>(.*?))\[/code\]\r\n|\[code=(?<language>[^\]]*)\](?<inner>(.*?))\[/code\]", Options), @"<div class=""code"">${inner}</div>") { RuleRank = 2 }); // handle custom BBCode this.AddCustomBBCodeRules(ruleEngine); // add rule for code block type with no syntax highlighting ruleEngine.AddRule( new SyntaxHighlighterRegexReplaceRule( isEditMode, new Regex(@"\[code\](?<inner>(.*?))\[/code\]\r\n|\[code\](?<inner>(.*?))\[/code\]", Options), @"<div class=""code"">${inner}</div>")); ruleEngine.AddRule( new QuoteRegexReplaceRule( @"\[quote=(?<quote>(.*?))]", @"<blockquote class=""blockquote blockquote-custom pt-3 px-1 pb-1 mb-4 border border-secondary rounded""> <div class=""blockquote-custom-icon bg-secondary""> <i class=""fa fa-quote-left fa-sm link-light""></i> </div>${quote}", Options)); // simple open quote tag var simpleOpenQuoteReplace = $@"<blockquote class=""blockquote blockquote-custom pt-3 px-1 pb-1 mb-4 border border-secondary rounded""> <div class=""blockquote-custom-icon bg-secondary""> <i class=""fa fa-quote-left fa-sm link-light""></i> </div> <footer class=""blockquote-footer""><cite>{localQuoteStr}</cite></footer> <p class=""mb-0"">"; ruleEngine.AddRule( new SimpleRegexReplaceRule(@"\[quote\]", simpleOpenQuoteReplace, Options) { RuleRank = 62 }); // and finally the closing quote tag ruleEngine.AddRule( new SingleRegexReplaceRule(@"\[/quote\]", "</p></blockquote>", Options) { RuleRank = 63 }); }
/// <summary> /// Creates the rules that convert <see cref="YafBBCode" /> to HTML /// </summary> /// <param name="ruleEngine">The rule Engine.</param> /// <param name="isHtml">if set to <c>true</c> [is HTML].</param> /// <param name="doFormatting">The do Formatting.</param> /// <param name="targetBlankOverride">The target Blank Override.</param> /// <param name="useNoFollow">The use No Follow.</param> /// <param name="convertBBQuotes">The convert BB Quotes.</param> public void CreateBBCodeRules( IProcessReplaceRules ruleEngine, bool isHtml, bool doFormatting, bool targetBlankOverride, bool useNoFollow, bool convertBBQuotes) { var target = this.Get <YafBoardSettings>().BlankLinks || targetBlankOverride ? "target=\"_blank\"" : string.Empty; var nofollow = useNoFollow ? "rel=\"nofollow\"" : string.Empty; var classModal = string.Empty; // pull localized strings var localQuoteStr = this.Get <ILocalization>().GetText("COMMON", "BBCODE_QUOTE"); // handle font sizes -- this rule class internally handles the "size" variable ruleEngine.AddRule( new FontSizeRegexReplaceRule( @"\[size=(?<size>(.*?))\](?<inner>(.*?))\[/size\]", @"<span style=""font-size:${size}"">${inner}</span>", Options)); if (doFormatting) { ruleEngine.AddRule(new CodeRegexReplaceRule(_rgxNoParse, @"${inner}")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxBold, "<strong>${inner}</strong>")); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxStrike, "<s>${inner}</s>", Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxItalic, "<em>${inner}</em>", Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxUnderline, "<u>${inner}</u>", Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxHighlighted, @"<mark>${inner}</mark>", Options)); // e-mails ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxEmail2, "<a href=\"mailto:${email}\">${inner} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>", new[] { "email" })); ruleEngine.AddRule(new SimpleRegexReplaceRule(_rgxEmail1, @"<a href=""mailto:${inner}"">${inner}</a>")); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl2, "<a {0} {1} href=\"${http}${url}\" title=\"${http}${url}\">${inner} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", nofollow), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" }) { RuleRank = 10 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxUrl1, "<a {0} {1} href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", nofollow), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50) { RuleRank = 11 }); // urls ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxUrl3, "${before}<a {0} {1} href=\"${inner}\" title=\"${inner}\">${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", nofollow), new[] { "before" }, new[] { string.Empty }, 50) { RuleRank = 12 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxUrl4, "${before}<a {0} {1} href=\"${inner}\" title=\"${inner}\">${innertrunc} <i class=\"fa fa-external-link-alt fa-fw\"></i></a>" .Replace("{0}", target).Replace("{1}", nofollow), new[] { "before" }, new[] { string.Empty }, 50) { RuleRank = 13 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl2, "<a {0} {1} {2} href=\"#\" data-href=\"${http}${url}\" title=\"${http}${url}\">${inner}</a>" .Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", classModal), new[] { "url", "http" }, new[] { string.Empty, string.Empty // "http://" })); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxModalUrl1, "<a {0} {1} {2} href=\"#\" data-href=\"${http}${inner}\" title=\"${http}${inner}\">${http}${innertrunc}</a>" .Replace("{0}", target).Replace("{1}", nofollow).Replace("{2}", classModal), new[] { "http" }, new[] { string.Empty, string.Empty // "http://" }, 50)); // font ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxFont, "<span style=\"font-family:${font}\">${inner}</span>", Options, new[] { "font" })); // color ruleEngine.AddRule( new VariableRegexReplaceRule( _RgxColor, "<span style=\"color:${color}\">${inner}</span>", Options, new[] { "color" })); // lists ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxList1, "<ul>${inner}</ul>", Options)); /*ruleEngine.AddRule( * new VariableRegexReplaceRule(_rgxList2, "<ol type=\"${type}\">${inner}</ol>", _options, new[] { "type" }));*/ ruleEngine.AddRule( new SimpleRegexReplaceRule( _RgxListNumber, "<ol style=\"list-style-type:number\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( _RgxListLowerRoman, "<ol style=\"list-style-type:lower-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( _RgxListUpperRoman, "<ol style=\"list-style-type:upper-roman\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( _RgxListLowerAlpha, "<ol style=\"list-style-type:lower-alpha\">${inner}</ol>", RegexOptions.Singleline)); ruleEngine.AddRule( new SimpleRegexReplaceRule( _RgxListUpperAlpha, "<ol style=\"list-style-type:upper-alpha\">${inner}</ol>", RegexOptions.Singleline)); // bullets ruleEngine.AddRule(new SingleRegexReplaceRule(_RgxBullet, "<li>", Options)); // alignment ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxCenter, "<div align=\"center\">${inner}</div>", Options)); ruleEngine.AddRule(new SimpleRegexReplaceRule(_RgxLeft, "<div align=\"left\">${inner}</div>", Options)); ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxRight, "<div align=\"right\">${inner}</div>", Options)); // indent ruleEngine.AddRule( new SimpleRegexReplaceRule(_RgxIndent, "<div style=\"margin-left:40px\">${inner}</div>", Options)); // image ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImg, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"img-user-posted img-thumbnail\" style=\"max-width:auto;max-height:${height}px;\" />", new[] { "http", "height" }, new[] { "http://", this.Get <YafBoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 70 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgEmptyTitle, "<img src=\"${http}${inner}\" alt=\"UserPostedImage\" class=\"img-user-posted img-thumbnail\" style=\"max-width:auto;max-height:${height}px;\" />", new[] { "http", "height" }, new[] { "http://", this.Get <YafBoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 71 }); ruleEngine.AddRule( new VariableRegexReplaceRule( _rgxImgTitle, "<img src=\"${http}${inner}\" alt=\"${description}\" title=\"${description}\" class=\"img-user-posted img-thumbnail\" style=\"max-width:auto;max-height:${height}px;\" />", new[] { "http", "description", "height" }, new[] { "http://", string.Empty, this.Get <YafBoardSettings>().ImageThumbnailMaxHeight.ToString() }) { RuleRank = 72 }); // basic hr and br rules var hrRule = new SingleRegexReplaceRule( _RgxHr, "<hr />", RegexOptions.IgnoreCase | RegexOptions.Multiline); ruleEngine.AddRule(new SingleRegexReplaceRule(@"\[br\]", "</p>", Options)); // Multiline, since ^ must match beginning of line var brRule = new SingleRegexReplaceRule( _RgxBr, "<br />", RegexOptions.IgnoreCase | RegexOptions.Multiline) { RuleRank = hrRule.RuleRank + 1 }; // Ensure the newline rule is processed after the HR rule, otherwise the newline characters in the HR regex will never match ruleEngine.AddRule(hrRule); ruleEngine.AddRule(!isHtml ? brRule : new SingleRegexReplaceRule(@"\r\n", "<p>", Options)); } if (convertBBQuotes) { // add rule for code block type with syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule( _regexCodeWithLanguage, @"<div class=""code"">${inner}</div>") { RuleRank = 2 }); // handle custom YafBBCode this.AddCustomBBCodeRules(ruleEngine); // add rule for code block type with no syntax highlighting ruleEngine.AddRule( new SyntaxHighlightedCodeRegexReplaceRule(_rgxCode1, @"<div class=""code"">${inner}</div>")); ruleEngine.AddRule( new QuoteRegexReplaceRule( OpenQuoteUserIdRegex, @"<div class=""card bg-light mb-3"">${quote}", Options)); // simple open quote tag var simpleOpenQuoteReplace = $@"<div class=""card bg-light mb-3""><div class=""card-header text-muted"">{localQuoteStr}</div><div class=""card-body""><p class=""card-text"">"; ruleEngine.AddRule( new SimpleRegexReplaceRule(OpenQuoteRegex, simpleOpenQuoteReplace, Options) { RuleRank = 62 }); // and finally the closing quote tag ruleEngine.AddRule( new SingleRegexReplaceRule(CloseQuoteRegex, "</div></div>", Options) { RuleRank = 63 }); } // post and topic rules... ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxPost, @"<a href=""${post}"" title=""${inner}"">${inner}</a>", Options)); ruleEngine.AddRule( new PostTopicRegexReplaceRule( _RgxTopic, @"<a href=""${topic}"" title=""${inner}"">${inner}</a>", Options)); }