PJonDevelopment refactored to use generic context

main
Inga 🏳‍🌈 13 years ago
parent 88fa0e7758
commit 9847264000
  1. 4
      FLocal.Common/BBCodes/AbstractLocalLink.cs
  2. 4
      FLocal.Common/BBCodes/B.cs
  3. 2
      FLocal.Common/BBCodes/Code.cs
  4. 4
      FLocal.Common/BBCodes/ECode.cs
  5. 4
      FLocal.Common/BBCodes/FUrl.cs
  6. 4
      FLocal.Common/BBCodes/Font.cs
  7. 4
      FLocal.Common/BBCodes/FontColor.cs
  8. 4
      FLocal.Common/BBCodes/FontSize.cs
  9. 4
      FLocal.Common/BBCodes/Google.cs
  10. 4
      FLocal.Common/BBCodes/I.cs
  11. 2
      FLocal.Common/BBCodes/Image.cs
  12. 4
      FLocal.Common/BBCodes/List.cs
  13. 2
      FLocal.Common/BBCodes/ListElem.cs
  14. 4
      FLocal.Common/BBCodes/Lurk.cs
  15. 2
      FLocal.Common/BBCodes/Math.cs
  16. 4
      FLocal.Common/BBCodes/Quote.cs
  17. 4
      FLocal.Common/BBCodes/QuoteSkipper.cs
  18. 4
      FLocal.Common/BBCodes/RuWiki.cs
  19. 4
      FLocal.Common/BBCodes/S.cs
  20. 4
      FLocal.Common/BBCodes/Spoiler.cs
  21. 2
      FLocal.Common/BBCodes/Tex.cs
  22. 4
      FLocal.Common/BBCodes/U.cs
  23. 2
      FLocal.Common/BBCodes/UploadImage.cs
  24. 4
      FLocal.Common/BBCodes/UploadLink.cs
  25. 4
      FLocal.Common/BBCodes/Url.cs
  26. 2
      FLocal.Common/BBCodes/User.cs
  27. 4
      FLocal.Common/BBCodes/Wiki.cs
  28. 7
      FLocal.Common/BBCodes/helpers/BBCode.cs
  29. 10
      FLocal.Common/BBCodes/helpers/IPostParsingContext.cs
  30. 2
      FLocal.Common/FLocal.Common.csproj
  31. 24
      FLocal.Common/UBBParser.cs
  32. 36
      FLocal.Common/dataobjects/User.cs
  33. 11
      FLocal.Common/helpers/DelegatePostParsingContext.cs
  34. 2
      FLocal.IISHandler/handlers/response/UserRepliesHandler.cs
  35. 244
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeConfiguration.vb
  36. 128
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeDocument.vb
  37. 436
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeElement.vb
  38. 136
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeElementFactory.vb
  39. 180
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeElementTypeDictionary.vb
  40. 136
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeNode.vb
  41. 130
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeNodeCollection.vb
  42. 598
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeParser.vb
  43. 102
      ThirdParty/PJonDevelopment.BBCode/Classes/BBCodeText.vb
  44. 746
      ThirdParty/PJonDevelopment.BBCode/Modules/Utils.vb

@ -16,11 +16,11 @@ namespace FLocal.Common.BBCodes {
get;
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
var url = this.url;
var name = this.Safe(url.title);
if(this.Default != null) {
name = this.GetInnerHTML(formatter);
name = this.GetInnerHTML(context, formatter);
}
return string.Format("<a href=\"{0}\">{1}</a>", url.canonical, url.title);
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("b") {
}
public override string Format(ITextFormatter formatter) {
return "<b>" + this.GetInnerHTML(formatter) + "</b>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<b>" + this.GetInnerHTML(context, formatter) + "</b>";
}
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("code") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<pre>" + System.Web.HttpUtility.HtmlEncode(this.InnerBBCode) + "</pre><br/>";
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("ecode") {
}
public override string Format(ITextFormatter formatter) {
return this.GetInnerHTML(new BBCodeHtmlFormatter());
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return this.GetInnerHTML(context, new BBCodeHtmlFormatter());
}
}

@ -11,11 +11,11 @@ namespace FLocal.Common.BBCodes {
: base("furl") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string rawUrl = this.DefaultOrValue;
string title = null;
if(rawUrl.ToLower() != this.InnerText.ToLower()) {
title = this.GetInnerHTML(formatter);
title = this.GetInnerHTML(context, formatter);
}
return UrlProcessor.ProcessLink(rawUrl, title, false);
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("font") {
}
public override string Format(ITextFormatter formatter) {
return "<font face=\"" + this.Default + "\">" + this.GetInnerHTML(formatter) + "</font>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<font face=\"" + this.Default + "\">" + this.GetInnerHTML(context, formatter) + "</font>";
}
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("color") {
}
public override string Format(ITextFormatter formatter) {
return "<font color=\"" + this.Default + "\">" + this.GetInnerHTML(formatter) + "</font>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<font color=\"" + this.Default + "\">" + this.GetInnerHTML(context, formatter) + "</font>";
}
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("size") {
}
public override string Format(ITextFormatter formatter) {
return "<font size=\"" + this.Default + "\">" + this.GetInnerHTML(formatter) + "</font>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<font size=\"" + this.Default + "\">" + this.GetInnerHTML(context, formatter) + "</font>";
}
}

@ -12,8 +12,8 @@ namespace FLocal.Common.BBCodes {
: base("google") {
}
public override string Format(ITextFormatter formatter) {
return "<a href=\"http://lmgtfy.com/?q=" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">g:" + this.GetInnerHTML(formatter) + "</a>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<a href=\"http://lmgtfy.com/?q=" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">g:" + this.GetInnerHTML(context, formatter) + "</a>";
}
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("i") {
}
public override string Format(ITextFormatter formatter) {
return "<i>" + this.GetInnerHTML(formatter) + "</i>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<i>" + this.GetInnerHTML(context, formatter) + "</i>";
}
}

@ -10,7 +10,7 @@ namespace FLocal.Common.BBCodes {
public Image() : base("image") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
var urlInfo = UrlProcessor.Process(this.InnerText);
if (urlInfo.isLocal && urlInfo.relativeUrl.StartsWith("/user/upload/")) {
return "<f:img><f:src>" + urlInfo.relativeUrl + "</f:src><f:alt>" + urlInfo.relativeUrl + "</f:alt></f:img>";

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("list") {
}
public override string Format(ITextFormatter formatter) {
return "<ul>" + this.GetInnerHTML(formatter) + "</ul>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<ul>" + this.GetInnerHTML(context, formatter) + "</ul>";
}
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("*") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
// return "<li>" + this.GetInnerHTML(formatter) + "</li>";
return "<li>";
}

@ -12,8 +12,8 @@ namespace FLocal.Common.BBCodes {
: base("lurk") {
}
public override string Format(ITextFormatter formatter) {
return "<a href=\"http://lurkmore.ru/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">l:" + this.GetInnerHTML(formatter) + "</a>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<a href=\"http://lurkmore.ru/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">l:" + this.GetInnerHTML(context, formatter) + "</a>";
}
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("math") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string tex = "$$" + this.InnerBBCode + "$$";
var upload = helpers.TexProcessor.getCompiled(tex);
return "<f:img><f:src>/Upload/Item/" + upload.id.ToString() + "/</f:src><f:alt>" + this.Safe(tex) + "</f:alt></f:img>";

@ -12,8 +12,8 @@ namespace FLocal.Common.BBCodes {
: base("quote") {
}
public override string Format(ITextFormatter formatter) {
string inner = this.GetInnerHTML(formatter).TrimHtml();
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string inner = this.GetInnerHTML(context, formatter).TrimHtml();
if(inner == "") return "";
string marker = this.Default;
if(marker == null) marker = "Quote:";

@ -10,7 +10,7 @@ namespace FLocal.Common.BBCodes {
public QuoteSkipper() : base("quoteskipper") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
if(this.Name.ToLower() == "q" || this.Name.ToLower() == "quote") {
return "";
} else if(this.Name.ToLower() == "code") {
@ -36,7 +36,7 @@ namespace FLocal.Common.BBCodes {
}
sb.Append("]");
if(this.RequireClosingTag) {
sb.Append(this.GetInnerHTML(formatter));
sb.Append(this.GetInnerHTML(context, formatter));
sb.Append("[/");
sb.Append(name);
sb.Append("]");

@ -12,8 +12,8 @@ namespace FLocal.Common.BBCodes {
: base("ruwiki") {
}
public override string Format(ITextFormatter formatter) {
return "<a href=\"http://ru.wikipedia.org/wiki/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">в:" + this.GetInnerHTML(formatter) + "</a>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<a href=\"http://ru.wikipedia.org/wiki/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">в:" + this.GetInnerHTML(context, formatter) + "</a>";
}
}

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("s") {
}
public override string Format(ITextFormatter formatter) {
return "<s>" + this.GetInnerHTML(formatter) + "</s>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<s>" + this.GetInnerHTML(context, formatter) + "</s>";
}
}

@ -11,10 +11,10 @@ namespace FLocal.Common.BBCodes {
: base("spoiler") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string marker = this.Default;
if(marker == null) marker = "Spoiler";
return "<blockquote spoiler><font opener class=\"small\" onClick=\"showSpoiler(this)\">" + marker + "</font><hr/><div inner name=\"inner\" style=\"display:none\">" + this.GetInnerHTML(formatter).Trim() + "</div><hr/></blockquote><br/>";
return "<blockquote spoiler><font opener class=\"small\" onClick=\"showSpoiler(this)\">" + marker + "</font><hr/><div inner name=\"inner\" style=\"display:none\">" + this.GetInnerHTML(context, formatter).Trim() + "</div><hr/></blockquote><br/>";
}
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("tex") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string tex = this.InnerBBCode;
var upload = helpers.TexProcessor.getCompiled(tex);
return "<f:img><f:src>/Upload/Item/" + upload.id.ToString() + "/</f:src><f:alt>" + this.Safe(tex) + "</f:alt></f:img>";

@ -11,8 +11,8 @@ namespace FLocal.Common.BBCodes {
: base("u") {
}
public override string Format(ITextFormatter formatter) {
return "<u>" + this.GetInnerHTML(formatter) + "</u>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<u>" + this.GetInnerHTML(context, formatter) + "</u>";
}
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("uploadimage") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
var upload = dataobjects.Upload.LoadById(int.Parse(this.InnerText));
var name = upload.filename;
return "<f:img><f:src>/Upload/Item/" + upload.id.ToString() + "/</f:src><f:alt>" + this.Safe(upload.filename) + "</f:alt></f:img>";

@ -11,11 +11,11 @@ namespace FLocal.Common.BBCodes {
: base("uploadlink") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
var upload = dataobjects.Upload.LoadById(int.Parse(this.DefaultOrValue));
var name = this.Safe(upload.filename);
if(this.Default != null) {
name = this.GetInnerHTML(formatter);
name = this.GetInnerHTML(context, formatter);
}
return "<a href=\"/Upload/Info/" + upload.id.ToString() + "/\">" + name + "</a>";
}

@ -11,11 +11,11 @@ namespace FLocal.Common.BBCodes {
: base("url") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
string rawUrl = this.DefaultOrValue;
string title = null;
if(rawUrl.ToLower() != this.InnerText.ToLower()) {
title = this.GetInnerHTML(formatter);
title = this.GetInnerHTML(context, formatter);
}
return UrlProcessor.ProcessLink(rawUrl, title, true);
}

@ -11,7 +11,7 @@ namespace FLocal.Common.BBCodes {
: base("user") {
}
public override string Format(ITextFormatter formatter) {
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
var user = dataobjects.User.LoadByName(this.DefaultOrValue);
var url = new URL.users.user.Info(user.id.ToString(), null);
return String.Format("<a class=\"separate UG_{0}\" href=\"{1}\">{2}</a>", this.Safe(user.userGroup.name), url.canonical, this.Safe(user.name));

@ -12,8 +12,8 @@ namespace FLocal.Common.BBCodes {
: base("wiki") {
}
public override string Format(ITextFormatter formatter) {
return "<a href=\"http://en.wikipedia.org/wiki/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">w:" + this.GetInnerHTML(formatter) + "</a>";
public override string Format(IPostParsingContext context, ITextFormatter formatter) {
return "<a href=\"http://en.wikipedia.org/wiki/" + HttpUtility.UrlPathEncode(this.DefaultOrValue) + "\">w:" + this.GetInnerHTML(context, formatter) + "</a>";
}
}

@ -2,18 +2,19 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FLocal.Common.helpers;
namespace FLocal.Common.BBCodes {
abstract class BBCode : PJonDevelopment.BBCode.BBCodeElement {
abstract class BBCode : PJonDevelopment.BBCode.BBCodeElement<IPostParsingContext> {
public BBCode(string name)
: base(name) {
}
protected string GetInnerHTML(PJonDevelopment.BBCode.ITextFormatter formatter) {
protected string GetInnerHTML(IPostParsingContext context, PJonDevelopment.BBCode.ITextFormatter formatter) {
StringBuilder builder = new StringBuilder();
foreach (var node in this.Nodes) {
builder.Append(node.Format(formatter));
builder.Append(node.Format(context, formatter));
}
return builder.ToString();
}

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FLocal.Common.dataobjects;
namespace FLocal.Common.BBCodes {
public interface IPostParsingContext {
}
}

@ -123,6 +123,8 @@
<Compile Include="dataobjects\User.cs" />
<Compile Include="dataobjects\AccountSettings.cs" />
<Compile Include="dataobjects\UserGroup.cs" />
<Compile Include="helpers\DelegatePostParsingContext.cs" />
<Compile Include="BBCodes\helpers\IPostParsingContext.cs" />
<Compile Include="IComplexSqlObjectTableSpec.cs" />
<Compile Include="IOutputParams.cs" />
<Compile Include="ISqlObjectTableSpec.cs" />

@ -7,6 +7,7 @@ using System.Text.RegularExpressions;
using PJonDevelopment.BBCode;
using System.IO;
using Web.Core;
using FLocal.Common.helpers;
namespace FLocal.Common {
public static class UBBParser {
@ -108,14 +109,14 @@ namespace FLocal.Common {
public static readonly BBParserGateway instance = new BBParserGateway();
private BBCodeParser parser;
private BBCodeParser<BBCodes.IPostParsingContext> parser;
private ITextFormatter formatter;
private BBCodeParser quotesParser;
private BBCodeParser<BBCodes.IPostParsingContext> quotesParser;
private ITextFormatter simpleFormatter;
private BBParserGateway() {
this.parser = new BBCodeParser();
this.parser = new BBCodeParser<BBCodes.IPostParsingContext>();
this.parser.ElementTypes.Add("b", typeof(BBCodes.B), true);
this.parser.ElementTypes.Add("code", typeof(BBCodes.Code), true);
this.parser.ElementTypes.Add("ecode", typeof(BBCodes.ECode), true);
@ -145,30 +146,33 @@ namespace FLocal.Common {
this.parser.ElementTypes.Add("wiki", typeof(BBCodes.Wiki), true);
this.parser.ElementTypes.Add("ruwiki", typeof(BBCodes.RuWiki), true);
this.formatter = TextFormatter.instance;
this.quotesParser = new BBCodeParser();
this.quotesParser = new BBCodeParser<BBCodes.IPostParsingContext>();
foreach(var elementType in this.parser.ElementTypes) {
this.quotesParser.ElementTypes.Add(elementType.Key, typeof(BBCodes.QuoteSkipper), elementType.Value.RequireClosingTag);
}
this.simpleFormatter = SimpleFormatter.instance;
}
public string Parse(string input) {
string result = this.parser.Parse(input).Format(this.formatter);
public string Parse(BBCodes.IPostParsingContext context, string input) {
string result = this.parser.Parse(input).Format(context, this.formatter);
if(result.EndsWith("<br/>")) result = result.Substring(0, result.Length - 5);
return result;
}
public string ParseQuote(string input) {
string result = this.quotesParser.Parse(input).Format(this.simpleFormatter);
string result = this.quotesParser.Parse(input).Format(new DelegatePostParsingContext(), this.simpleFormatter);
return result;
}
}
public static string UBBToIntermediate(BBCodes.IPostParsingContext context, string UBB) {
return BBParserGateway.instance.Parse(context, UBB);
}
public static string UBBToIntermediate(string UBB) {
//return HttpUtility.HtmlEncode(UBB).Replace(Util.EOL, "<br/>" + Util.EOL);
return BBParserGateway.instance.Parse(UBB);
return UBBToIntermediate(new DelegatePostParsingContext(), UBB);
}
public static string ShallerToUBB(string shaller) {

@ -253,38 +253,18 @@ namespace FLocal.Common.dataobjects {
);
}
public IEnumerable<Post> getReplies(Diapasone diapasone, bool isAscending) {
JoinSpec parent = new JoinSpec(
Post.TableSpec.instance.getColumnSpec(Post.TableSpec.FIELD_PARENTPOSTID),
Post.TableSpec.instance,
"parent"
);
public IEnumerable<Post> getMentions(Diapasone diapasone, bool isAscending) {
return Post.LoadByIds(
from stringId in Config.instance.mainConnection.LoadIdsByConditions(
Post.TableSpec.instance,
new ComplexCondition(
ConditionsJoinType.AND,
new ComparisonCondition(
parent.additionalTable.getColumnSpec(Post.TableSpec.FIELD_POSTERID),
ComparisonType.EQUAL,
this.id.ToString()
),
new ComparisonCondition(
Post.TableSpec.instance.getColumnSpec(Post.TableSpec.FIELD_POSTERID),
ComparisonType.NOTEQUAL,
this.id.ToString()
)
Mention.TableSpec.instance,
new ComparisonCondition(
Mention.TableSpec.instance.getColumnSpec(Mention.TableSpec.FIELD_MENTIONEDUSERID),
ComparisonType.EQUAL,
this.id.ToString()
),
diapasone,
new JoinSpec[] {
parent
},
new SortSpec[] {
new SortSpec(
Post.TableSpec.instance.getIdSpec(),
isAscending
),
}
Mention.TableSpec.instance.getColumnSpec(Mention.TableSpec.FIELD_POSTID),
new SortSpec(Mention.TableSpec.instance.getIdSpec(), isAscending)
) select int.Parse(stringId)
);
}

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FLocal.Common.dataobjects;
using FLocal.Common.BBCodes;
namespace FLocal.Common.helpers {
class DelegatePostParsingContext : IPostParsingContext {
}
}

@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers.response {
override protected IEnumerable<XElement> getUserSpecificData(WebContext context, User user) {
PageOuter pageOuter = PageOuter.createFromUrl(this.url, context.userSettings.postsPerPage);
IEnumerable<Post> posts = user.getReplies(pageOuter, pageOuter.descendingDirection);
IEnumerable<Post> posts = user.getMentions(pageOuter, pageOuter.descendingDirection);
return new XElement[] {
user.exportToXmlForViewing(context),

@ -22,127 +22,127 @@ Imports System.Xml.Serialization
''' </summary>
<Serializable()> _
<XmlRoot(ElementName:=STR_BBCodeConfigurationXmlElement, [Namespace]:=STR_BBCodeSchemaNamespace)> _
Public NotInheritable Class BBCodeConfiguration
Implements IXmlSerializable
Private Shared ReadOnly __CurrentVersion As New System.Version(1, 0)
Private __Version As System.Version
Private __Dictionary As BBCodeElementDictionary
Private __ElementTypes As BBCodeElementTypeDictionary
''' <summary>Initializes an instance of the <see cref="BBCodeConfiguration" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
__Version = New Version(1, 0)
End Sub
''' <summary>
''' Gets the version of the configuration file.
''' </summary>
Public Property Version() As System.Version
Get
Return __Version
End Get
Private Set(ByVal value As System.Version)
If (value > __CurrentVersion) Then
Throw New ArgumentException("Unrecognized version.")
End If
__Version = value
End Set
End Property
''' <summary>
''' Gets the dictionary configuration.
''' </summary>
<XmlArrayItem()> _
Public ReadOnly Property Dictionary() As BBCodeElementDictionary
Get
If (__Dictionary Is Nothing) Then
__Dictionary = New BBCodeElementDictionary()
End If
Return __Dictionary
End Get
End Property
''' <summary>
''' Gets the factory configuration.
''' </summary>
<XmlArrayItem()> _
Public ReadOnly Property ElementTypes() As BBCodeElementTypeDictionary
Get
If (__ElementTypes Is Nothing) Then
__ElementTypes = New BBCodeElementTypeDictionary()
End If
Return __ElementTypes
End Get
End Property
''' <summary>This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute" /> to the class.</summary>
''' <returns>An <see cref="T:System.Xml.Schema.XmlSchema" /> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)" /> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)" /> method.</returns>
Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
Return Nothing
End Function
''' <summary>Generates an object from its XML representation.</summary>
''' <param name="reader">The <see cref="T:System.Xml.XmlReader" /> stream from which the object is deserialized.</param>
Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
'*
'* Check the name of the element
'*
If (reader.NamespaceURI <> STR_BBCodeSchemaNamespace) OrElse (reader.LocalName <> STR_BBCodeConfigurationXmlElement) Then
Exit Sub
End If
'*
'* Gets the version of the configuration
'*
Dim versionString = reader.GetAttribute("version")
If (Not String.IsNullOrEmpty(versionString)) Then
Me.Version = New System.Version(versionString)
End If
'*
'* Move to the first item
'*
reader.Read()
Dim dictionarySerializer = New XmlSerializer(GetType(BBCodeElementDictionary))
Dim typesSerializer = New XmlSerializer(GetType(BBCodeElementTypeDictionary))
__ElementTypes = Nothing
__Dictionary = Nothing
If (reader.LocalName = STR_BBCodeElementTypesXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__ElementTypes = typesSerializer.Deserialize(reader)
End If
If (reader.LocalName = STR_BBCodeDictionaryXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__Dictionary = dictionarySerializer.Deserialize(reader)
End If
If (__ElementTypes Is Nothing AndAlso reader.LocalName = STR_BBCodeElementTypesXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__ElementTypes = typesSerializer.Deserialize(reader)
End If
End Sub
''' <summary>Converts an object into its XML representation.</summary>
''' <param name="writer">The <see cref="T:System.Xml.XmlWriter" /> stream to which the object is serialized.</param>
Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
Dim dictionarySerializer = New XmlSerializer(GetType(BBCodeElementDictionary))
Dim typesSerializer = New XmlSerializer(GetType(BBCodeElementTypeDictionary))
If (ElementTypes.Count > 0) Then
typesSerializer.Serialize(writer, ElementTypes)
End If
If (Dictionary.Count > 0) Then
dictionarySerializer.Serialize(writer, Dictionary)
End If
End Sub
Public NotInheritable Class BBCodeConfiguration(Of TContext As Class)
Implements IXmlSerializable
Private Shared ReadOnly __CurrentVersion As New System.Version(1, 0)
Private __Version As System.Version
Private __Dictionary As BBCodeElementDictionary
Private __ElementTypes As BBCodeElementTypeDictionary(Of TContext)
''' <summary>Initializes an instance of the <see cref="BBCodeConfiguration" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
__Version = New Version(1, 0)
End Sub
''' <summary>
''' Gets the version of the configuration file.
''' </summary>
Public Property Version() As System.Version
Get
Return __Version
End Get
Private Set(ByVal value As System.Version)
If (value > __CurrentVersion) Then
Throw New ArgumentException("Unrecognized version.")
End If
__Version = value
End Set
End Property
''' <summary>
''' Gets the dictionary configuration.
''' </summary>
<XmlArrayItem()> _
Public ReadOnly Property Dictionary() As BBCodeElementDictionary
Get
If (__Dictionary Is Nothing) Then
__Dictionary = New BBCodeElementDictionary()
End If
Return __Dictionary
End Get
End Property
''' <summary>
''' Gets the factory configuration.
''' </summary>
<XmlArrayItem()> _
Public ReadOnly Property ElementTypes() As BBCodeElementTypeDictionary(Of TContext)
Get
If (__ElementTypes Is Nothing) Then
__ElementTypes = New BBCodeElementTypeDictionary(Of TContext)()
End If
Return __ElementTypes
End Get
End Property
''' <summary>This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute" /> to the class.</summary>
''' <returns>An <see cref="T:System.Xml.Schema.XmlSchema" /> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)" /> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)" /> method.</returns>
Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
Return Nothing
End Function
''' <summary>Generates an object from its XML representation.</summary>
''' <param name="reader">The <see cref="T:System.Xml.XmlReader" /> stream from which the object is deserialized.</param>
Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
'*
'* Check the name of the element
'*
If (reader.NamespaceURI <> STR_BBCodeSchemaNamespace) OrElse (reader.LocalName <> STR_BBCodeConfigurationXmlElement) Then
Exit Sub
End If
'*
'* Gets the version of the configuration
'*
Dim versionString = reader.GetAttribute("version")
If (Not String.IsNullOrEmpty(versionString)) Then
Me.Version = New System.Version(versionString)
End If
'*
'* Move to the first item
'*
reader.Read()
Dim dictionarySerializer = New XmlSerializer(GetType(BBCodeElementDictionary))
Dim typesSerializer = New XmlSerializer(GetType(BBCodeElementTypeDictionary(Of TContext)))
__ElementTypes = Nothing
__Dictionary = Nothing
If (reader.LocalName = STR_BBCodeElementTypesXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__ElementTypes = typesSerializer.Deserialize(reader)
End If
If (reader.LocalName = STR_BBCodeDictionaryXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__Dictionary = dictionarySerializer.Deserialize(reader)
End If
If (__ElementTypes Is Nothing AndAlso reader.LocalName = STR_BBCodeElementTypesXmlElement AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace) Then
__ElementTypes = typesSerializer.Deserialize(reader)
End If
End Sub
''' <summary>Converts an object into its XML representation.</summary>
''' <param name="writer">The <see cref="T:System.Xml.XmlWriter" /> stream to which the object is serialized.</param>
Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
Dim dictionarySerializer = New XmlSerializer(GetType(BBCodeElementDictionary))
Dim typesSerializer = New XmlSerializer(GetType(BBCodeElementTypeDictionary(Of TContext)))
If (ElementTypes.Count > 0) Then
typesSerializer.Serialize(writer, ElementTypes)
End If
If (Dictionary.Count > 0) Then
dictionarySerializer.Serialize(writer, Dictionary)
End If
End Sub
End Class

@ -18,77 +18,77 @@
''' <summary>
''' Represents a document writen in BBCode.
''' </summary>
Public NotInheritable Class BBCodeDocument
Public NotInheritable Class BBCodeDocument(Of TContext As Class)
Private __Text As String
Private __Parser As BBCodeParser
Private __Nodes As BBCodeNodeCollection
Private __Text As String
Private __Parser As BBCodeParser(Of TContext)
Private __Nodes As BBCodeNodeCollection(Of TContext)
''' <summary>Initializes an instance of the <see cref="BBCodeDocument" /> class.</summary>
''' <param name="parser">The <see cref="BBCodeParser"/> that created this instance.</param>
Friend Sub New(ByVal parser As BBCodeParser)
__Parser = parser
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeDocument" /> class.</summary>
''' <param name="parser">The <see cref="BBCodeParser"/> that created this instance.</param>
Friend Sub New(ByVal parser As BBCodeParser(Of TContext))
__Parser = parser
End Sub
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that is responsible for this <see cref="BBCodeDocument"/>.
''' </summary>
Friend ReadOnly Property Parser() As BBCodeParser
Get
Return __Parser
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that is responsible for this <see cref="BBCodeDocument"/>.
''' </summary>
Friend ReadOnly Property Parser() As BBCodeParser(Of TContext)
Get
Return __Parser
End Get
End Property
''' <summary>
''' Gets or sets the BBCode of the document.
''' </summary>
Public Property Text() As String
Get
Return __Text
End Get
Set(ByVal value As String)
__Text = value
Nodes.Clear()
Nodes.AddRange(Me.Parser.Parse(value).Nodes)
End Set
End Property
''' <summary>
''' Gets or sets the BBCode of the document.
''' </summary>
Public Property Text() As String
Get
Return __Text
End Get
Set(ByVal value As String)
__Text = value
Nodes.Clear()
Nodes.AddRange(Me.Parser.Parse(value).Nodes)
End Set
End Property
''' <summary>
''' Gets the <see cref="BBCodeNodeCollection"/> generated ba the BBCode text.
''' </summary>
''' <value>A <see cref="BBCodeNodeCollection"/> that represents the parsed text of the document.</value>
Public ReadOnly Property Nodes() As BBCodeNodeCollection
Get
If (__Nodes Is Nothing) Then
__Nodes = New BBCodeNodeCollection()
End If
Return __Nodes
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeNodeCollection"/> generated ba the BBCode text.
''' </summary>
''' <value>A <see cref="BBCodeNodeCollection"/> that represents the parsed text of the document.</value>
Public ReadOnly Property Nodes() As BBCodeNodeCollection(Of TContext)
Get
If (__Nodes Is Nothing) Then
__Nodes = New BBCodeNodeCollection(Of TContext)()
End If
Return __Nodes
End Get
End Property
''' <summary>
''' Returns the formatted text.
''' </summary>
''' <returns>The formatted text.</returns>
Public Function Format() As String
Return Format(New BBCodeHtmlFormatter())
End Function
''' <summary>
''' Returns the formatted text.
''' </summary>
''' <returns>The formatted text.</returns>
Public Function Format(ByVal context As TContext) As String
Return Format(context, New BBCodeHtmlFormatter())
End Function
''' <summary>
''' Returns the formatted text, using the specified <see cref="ITextFormatter"/>.
''' </summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter"/> interface.</param>
''' <returns>The formatted text.</returns>
Public Function Format(ByVal formatter As ITextFormatter) As String
Dim sb As New Text.StringBuilder()
For Each n In Nodes
sb.Append(n.Format(formatter))
Next
Return sb.ToString()
End Function
''' <summary>
''' Returns the formatted text, using the specified <see cref="ITextFormatter"/>.
''' </summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter"/> interface.</param>
''' <returns>The formatted text.</returns>
Public Function Format(ByVal context As TContext, ByVal formatter As ITextFormatter) As String
Dim sb As New Text.StringBuilder()
For Each n In Nodes
sb.Append(n.Format(context, formatter))
Next
Return sb.ToString()
End Function
Friend Sub SetText(ByVal text As String)
__Text = text
End Sub
Friend Sub SetText(ByVal text As String)
__Text = text
End Sub
End Class

@ -21,241 +21,241 @@ Imports System.Text.RegularExpressions
''' <summary>
''' Represents an BBCode element.
''' </summary>
Public Class BBCodeElement
Inherits BBCodeNode
Public Class BBCodeElement(Of TContext As Class)
Inherits BBCodeNode(Of TContext)
Private __Name As String
Private __Nodes As BBCodeNodeCollection
Private __Attributes As BBCodeAttributeDictionary
Private __ReplacementFormat As String = String.Empty
Private __RequireClosingTag As TriState = TriState.UseDefault
Private __IsValueFormatted As Boolean
Private __Name As String
Private __Nodes As BBCodeNodeCollection(Of TContext)
Private __Attributes As BBCodeAttributeDictionary
Private __ReplacementFormat As String = String.Empty
Private __RequireClosingTag As TriState = TriState.UseDefault
Private __IsValueFormatted As Boolean
Private Shared ReadOnly __RxAttribute As New Regex("\{(?<name>[_a-zA-Z0-9].*?)\}")
Private Shared ReadOnly __RxAttribute As New Regex("\{(?<name>[_a-zA-Z0-9].*?)\}")
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.</summary>
''' <param name="name">The name of the element.</param>
Protected Sub New(ByVal name As String)
__Name = name.ToUpperInvariant()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.</summary>
''' <param name="name">The name of the element.</param>
Protected Sub New(ByVal name As String)
__Name = name.ToUpperInvariant()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.</summary>
''' <param name="parser">The parser used to create this element.</param>
Friend Sub New(ByVal parser As BBCodeParser)
MyBase.New(parser)
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElement" /> class.</summary>
''' <param name="parser">The parser used to create this element.</param>
Friend Sub New(ByVal parser As BBCodeParser(Of TContext))
MyBase.New(parser)
End Sub
''' <summary>
''' Gets the name of the element.
''' </summary>
Public ReadOnly Property Name() As String
Get
Return __Name
End Get
End Property
''' <summary>
''' Gets the name of the element.
''' </summary>
Public ReadOnly Property Name() As String
Get
Return __Name
End Get
End Property
''' <summary>
''' Gets the replacement format for this element.
''' </summary>
''' <value>The replacement format.</value>
''' <remarks>
''' <para>In order to use the any parameter in the replacement format use the following syntax: {paramName}.</para>
''' <para/>
''' <para>The parameter names are case insensitive.</para>
''' <para/>
''' <para>There are two reserved parameter keywords for formatting: DEFAULT and VALUE.</para>
''' <para><c>DEFAULT</c> : The text following the first equal sign after the name of the BBCode element.</para>
''' <para><c>VALUE</c>: The HTML generated by the BBCode between the start and end element tag.</para>
''' <para><example>[url=http://tempuri.org]text[/url]</example></para>
''' <para>In the example above the parameter DEFAULT would have the value "http://tempuri.org", while VALUE would be "text".</para>
''' <para/>
''' <para>To replace [url=http://tempuri.org]text[/url] the with &lt;a href="http://tempuri.org"&gt;text&lt;/a&gt; the following ReplacementFormat should be used:</para>
''' <example>
''' &lt;a href="{default|value}"&gt;{value|default}&lt;/a&gt;
''' </example>
''' <para>The example above, will set the href attribute with either the default value or the text inside the [url] element. The pipe (|) implies in finding the first non-empty attribute.</para>
''' </remarks>
Public ReadOnly Property ReplacementFormat() As String
Get
If (String.IsNullOrEmpty(__ReplacementFormat)) Then
If (Me.Parser.Dictionary.ContainsKey(Me.Name)) Then
__ReplacementFormat = Me.Parser.Dictionary(Me.Name).ReplacementFormat
End If
End If
Return __ReplacementFormat
End Get
End Property
''' <summary>
''' Gets the replacement format for this element.
''' </summary>
''' <value>The replacement format.</value>
''' <remarks>
''' <para>In order to use the any parameter in the replacement format use the following syntax: {paramName}.</para>
''' <para/>
''' <para>The parameter names are case insensitive.</para>
''' <para/>
''' <para>There are two reserved parameter keywords for formatting: DEFAULT and VALUE.</para>
''' <para><c>DEFAULT</c> : The text following the first equal sign after the name of the BBCode element.</para>
''' <para><c>VALUE</c>: The HTML generated by the BBCode between the start and end element tag.</para>
''' <para><example>[url=http://tempuri.org]text[/url]</example></para>
''' <para>In the example above the parameter DEFAULT would have the value "http://tempuri.org", while VALUE would be "text".</para>
''' <para/>
''' <para>To replace [url=http://tempuri.org]text[/url] the with &lt;a href="http://tempuri.org"&gt;text&lt;/a&gt; the following ReplacementFormat should be used:</para>
''' <example>
''' &lt;a href="{default|value}"&gt;{value|default}&lt;/a&gt;
''' </example>
''' <para>The example above, will set the href attribute with either the default value or the text inside the [url] element. The pipe (|) implies in finding the first non-empty attribute.</para>
''' </remarks>
Public ReadOnly Property ReplacementFormat() As String
Get
If (String.IsNullOrEmpty(__ReplacementFormat)) Then
If (Me.Parser.Dictionary.ContainsKey(Me.Name)) Then
__ReplacementFormat = Me.Parser.Dictionary(Me.Name).ReplacementFormat
End If
End If
Return __ReplacementFormat
End Get
End Property
''' <summary>
''' Gets a value indicating if the element requires a closing tag.
''' </summary>
''' <value><c>True</c> if the element requires a closing tag; otherwise <c>False</c>.</value>
Public ReadOnly Property RequireClosingTag() As Boolean
Get
If (__RequireClosingTag = TriState.UseDefault) Then
If (Not String.IsNullOrEmpty(Me.Name) AndAlso Me.Parser.Dictionary.ContainsKey(Me.Name)) Then
__RequireClosingTag = If(Me.Parser.Dictionary(Me.Name).RequireClosingTag, TriState.True, TriState.False)
ElseIf (Not String.IsNullOrEmpty(Me.Name) AndAlso Me.Parser.ElementTypes.ContainsKey(Me.Name)) Then
__RequireClosingTag = If(Me.Parser.ElementTypes(Me.Name).RequireClosingTag, TriState.True, TriState.False)
End If
End If
Return (__RequireClosingTag = TriState.True)
End Get
End Property
''' <summary>
''' Gets a value indicating if the element requires a closing tag.
''' </summary>
''' <value><c>True</c> if the element requires a closing tag; otherwise <c>False</c>.</value>
Public ReadOnly Property RequireClosingTag() As Boolean
Get
If (__RequireClosingTag = TriState.UseDefault) Then
If (Not String.IsNullOrEmpty(Me.Name) AndAlso Me.Parser.Dictionary.ContainsKey(Me.Name)) Then
__RequireClosingTag = If(Me.Parser.Dictionary(Me.Name).RequireClosingTag, TriState.True, TriState.False)
ElseIf (Not String.IsNullOrEmpty(Me.Name) AndAlso Me.Parser.ElementTypes.ContainsKey(Me.Name)) Then
__RequireClosingTag = If(Me.Parser.ElementTypes(Me.Name).RequireClosingTag, TriState.True, TriState.False)
End If
End If
Return (__RequireClosingTag = TriState.True)
End Get
End Property
''' <summary>
''' Gets the list of attributes.
''' </summary>
Public ReadOnly Property Attributes() As BBCodeAttributeDictionary
Get
If (__Attributes Is Nothing) Then
__Attributes = New BBCodeAttributeDictionary
End If
Return __Attributes
End Get
End Property
''' <summary>
''' Gets the list of attributes.
''' </summary>
Public ReadOnly Property Attributes() As BBCodeAttributeDictionary
Get
If (__Attributes Is Nothing) Then
__Attributes = New BBCodeAttributeDictionary
End If
Return __Attributes
End Get
End Property
''' <summary>
''' Gets the list of sub nodes.
''' </summary>
Public ReadOnly Property Nodes() As BBCodeNodeCollection
Get
If (__Nodes Is Nothing) Then
__Nodes = New BBCodeNodeCollection(Me)
End If
Return __Nodes
End Get
End Property
''' <summary>
''' Gets the list of sub nodes.
''' </summary>
Public ReadOnly Property Nodes() As BBCodeNodeCollection(Of TContext)
Get
If (__Nodes Is Nothing) Then
__Nodes = New BBCodeNodeCollection(Of TContext)(Me)
End If
Return __Nodes
End Get
End Property
''' <summary>Transforms this instance of <see cref="BBCodeElement" /> into its desired text representation.</summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter" /> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter" />.</returns>
Public Overrides Function Format(ByVal formatter As ITextFormatter) As String
IsValueFormatted = False
Dim sb As New Text.StringBuilder(Me.ReplacementFormat)
Dim attribs = __RxAttribute.Matches(Me.ReplacementFormat)
For Each attrib As Match In attribs
sb.Replace(attrib.Value, GetAttribute(attrib.Groups("name").Value, formatter))
Next
If Not IsValueFormatted Then
sb.Append(GetAttribute("value", formatter))
End If
Return sb.ToString()
End Function
''' <summary>Transforms this instance of <see cref="BBCodeElement" /> into its desired text representation.</summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter" /> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter" />.</returns>
Public Overrides Function Format(ByVal context As TContext, ByVal formatter As ITextFormatter) As String
IsValueFormatted = False
Dim sb As New Text.StringBuilder(Me.ReplacementFormat)
Dim attribs = __RxAttribute.Matches(Me.ReplacementFormat)
For Each attrib As Match In attribs
sb.Replace(attrib.Value, GetAttribute(attrib.Groups("name").Value, context, formatter))
Next
If Not IsValueFormatted Then
sb.Append(GetAttribute("value", context, formatter))
End If
Return sb.ToString()
End Function
''' <summary>Gets or sets the inner </summary>
''' <value>The BBCode between the start and end tags.</value>
Public NotOverridable Overrides Property InnerBBCode() As String
Get
Dim sb As New System.Text.StringBuilder()
For Each n As BBCodeNode In Nodes
sb.Append(n.OuterBBCode)
Next
Return sb.ToString()
End Get
Set(ByVal value As String)
If Not RequireClosingTag Then
Throw New InvalidOperationException("The InnerBBCode property cannot be set for elements that does not require closing tags.")
End If
Me.Nodes.Clear()
Me.Nodes.AddRange(Me.Parser.Parse(value).Nodes)
End Set
End Property
''' <summary>Gets or sets the inner </summary>
''' <value>The BBCode between the start and end tags.</value>
Public NotOverridable Overrides Property InnerBBCode() As String
Get
Dim sb As New System.Text.StringBuilder()
For Each n As BBCodeNode(Of TContext) In Nodes
sb.Append(n.OuterBBCode)
Next
Return sb.ToString()
End Get
Set(ByVal value As String)
If Not RequireClosingTag Then
Throw New InvalidOperationException("The InnerBBCode property cannot be set for elements that does not require closing tags.")
End If
Me.Nodes.Clear()
Me.Nodes.AddRange(Me.Parser.Parse(value).Nodes)
End Set
End Property
''' <summary>Gets or sets the outer </summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode" /> .</value>
Public NotOverridable Overrides ReadOnly Property OuterBBCode() As String
Get
Dim sb As New Text.StringBuilder()
sb.Append("[")
sb.Append(Me.Name)
If ((Me.Attributes.Count = 1) AndAlso Me.Attributes.ContainsKey("default")) Then
sb.AppendFormat(CultureInfo.InvariantCulture, "={0}", Quote(Me.Attributes("default")))
Else
For Each key In Me.Attributes.Keys
sb.AppendFormat(CultureInfo.InvariantCulture, " {0}={1}", key, Quote(Me.Attributes(key)))
Next
End If
If (Me.RequireClosingTag) Then
sb.Append("]")
sb.Append(Me.InnerBBCode)
sb.Append("[/")
sb.Append(Me.Name)
End If
sb.Append("]")
Return sb.ToString()
End Get
End Property
''' <summary>Gets or sets the outer </summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode" /> .</value>
Public NotOverridable Overrides ReadOnly Property OuterBBCode() As String
Get
Dim sb As New Text.StringBuilder()
sb.Append("[")
sb.Append(Me.Name)
If ((Me.Attributes.Count = 1) AndAlso Me.Attributes.ContainsKey("default")) Then
sb.AppendFormat(CultureInfo.InvariantCulture, "={0}", Quote(Me.Attributes("default")))
Else
For Each key In Me.Attributes.Keys
sb.AppendFormat(CultureInfo.InvariantCulture, " {0}={1}", key, Quote(Me.Attributes(key)))
Next
End If
If (Me.RequireClosingTag) Then
sb.Append("]")
sb.Append(Me.InnerBBCode)
sb.Append("[/")
sb.Append(Me.Name)
End If
sb.Append("]")
Return sb.ToString()
End Get
End Property
''' <summary>Gets or sets the plain text of the node.</summary>
''' <value>The plain text between the start and end tags.</value>
Public NotOverridable Overrides Property InnerText() As String
Get
Dim sb As New Text.StringBuilder()
For Each n In Me.Nodes
sb.Append(n.InnerText)
Next
Return sb.ToString()
End Get
Set(ByVal value As String)
If (Not RequireClosingTag) Then
Throw New InvalidOperationException("The InnerText property cannot be set for elements that does not require closing tags.")
End If
''' <summary>Gets or sets the plain text of the node.</summary>
''' <value>The plain text between the start and end tags.</value>
Public NotOverridable Overrides Property InnerText() As String
Get
Dim sb As New Text.StringBuilder()
For Each n In Me.Nodes
sb.Append(n.InnerText)
Next
Return sb.ToString()
End Get
Set(ByVal value As String)
If (Not RequireClosingTag) Then
Throw New InvalidOperationException("The InnerText property cannot be set for elements that does not require closing tags.")
End If
'*
'* Removes all nodex from the element
'*
Me.Nodes.Clear()
If (Not String.IsNullOrEmpty(value)) Then
'*
'* Only append a BBCodeText element if the value is not empty
'*
Me.Nodes.Add(New BBCodeText(value))
End If
End Set
End Property
'*
'* Removes all nodex from the element
'*
Me.Nodes.Clear()
If (Not String.IsNullOrEmpty(value)) Then
'*
'* Only append a BBCodeText element if the value is not empty
'*
Me.Nodes.Add(New BBCodeText(Of TContext)(value))
End If
End Set
End Property
''' <summary>
''' Sets the element name of this instance.
''' </summary>
''' <param name="name">The new element name of this instance.</param>
Friend Sub SetName(ByVal name As String)
__Name = name
End Sub
''' <summary>
''' Sets the element name of this instance.
''' </summary>
''' <param name="name">The new element name of this instance.</param>
Friend Sub SetName(ByVal name As String)
__Name = name
End Sub
''' <summary>
''' Gets a value indicating wheter or not the <see cref="BBCodeElement.Nodes"/> have been formatted.
''' </summary>
''' <returns><c>True</c> if the values have been formatted; otherwise <c>False</c>.</returns>
Private Property IsValueFormatted() As Boolean
Get
Return __IsValueFormatted
End Get
Set(ByVal value As Boolean)
__IsValueFormatted = value
End Set
End Property
''' <summary>
''' Gets a value indicating wheter or not the <see cref="BBCodeElement.Nodes"/> have been formatted.
''' </summary>
''' <returns><c>True</c> if the values have been formatted; otherwise <c>False</c>.</returns>
Private Property IsValueFormatted() As Boolean
Get
Return __IsValueFormatted
End Get
Set(ByVal value As Boolean)
__IsValueFormatted = value
End Set
End Property
Private Function GetAttribute(ByVal name As String, ByVal formatter As ITextFormatter) As String
Dim attribs = name.ToUpperInvariant().Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
For Each attrib In attribs
If (String.CompareOrdinal(attrib, "VALUE") = 0) Then
IsValueFormatted = True
Dim sb As New Text.StringBuilder()
For Each node In Me.Nodes
sb.Append(node.Format(formatter))
Next
Return sb.ToString()
ElseIf (Me.Attributes.ContainsKey(attrib)) Then
Return (Me.Attributes.Item(attrib))
End If
Next
Return String.Empty
End Function
Private Function GetAttribute(ByVal name As String, ByVal context As TContext, ByVal formatter As ITextFormatter) As String
Dim attribs = name.ToUpperInvariant().Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
For Each attrib In attribs
If (String.CompareOrdinal(attrib, "VALUE") = 0) Then
IsValueFormatted = True
Dim sb As New Text.StringBuilder()
For Each node In Me.Nodes
sb.Append(node.Format(context, formatter))
Next
Return sb.ToString()
ElseIf (Me.Attributes.ContainsKey(attrib)) Then
Return (Me.Attributes.Item(attrib))
End If
Next
Return String.Empty
End Function
End Class

@ -18,84 +18,84 @@
''' <summary>
''' Creates instances of <see cref="BBCodeElement"/>.
''' </summary>
Friend NotInheritable Class BBCodeElementFactory
Friend NotInheritable Class BBCodeElementFactory(Of TContext As Class)
Private __Parser As BBCodeParser
Private __Parser As BBCodeParser(Of TContext)
''' <summary>Initializes an instance of the <see cref="BBCodeElementFactory" /> class.</summary>
''' <param name="parser">The <see cref="BBCodeParser"/> that will utilize the new instance of the <see cref="BBCodeElementFactory"/>.</param>
Friend Sub New(ByVal parser As BBCodeParser)
__Parser = parser
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeElementFactory" /> class.</summary>
''' <param name="parser">The <see cref="BBCodeParser"/> that will utilize the new instance of the <see cref="BBCodeElementFactory"/>.</param>
Friend Sub New(ByVal parser As BBCodeParser(Of TContext))
__Parser = parser
End Sub
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that utilizes this instance of the <see cref="BBCodeElementFactory"/>.
''' </summary>
Public ReadOnly Property Parser() As BBCodeParser
Get
Return __Parser
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that utilizes this instance of the <see cref="BBCodeElementFactory"/>.
''' </summary>
Public ReadOnly Property Parser() As BBCodeParser(Of TContext)
Get
Return __Parser
End Get
End Property
''' <summary>
''' Creates a new <see cref="BBCodeElement"/>.
''' </summary>
''' <param name="name">The name of the element.</param>
''' <param name="attributes">The attributes of the element.</param>
''' <returns>A new <see cref="BBCodeElement"/>.</returns>
Public Function CreateElement(ByVal name As String, ByVal attributes As BBCodeAttributeDictionary) As BBCodeElement
''' <summary>
''' Creates a new <see cref="BBCodeElement"/>.
''' </summary>
''' <param name="name">The name of the element.</param>
''' <param name="attributes">The attributes of the element.</param>
''' <returns>A new <see cref="BBCodeElement"/>.</returns>
Public Function CreateElement(ByVal name As String, ByVal attributes As BBCodeAttributeDictionary) As BBCodeElement(Of TContext)
Dim el As BBCodeElement
Dim el As BBCodeElement(Of TContext)
'*
'* Check if we have a different type to create
'*
If (Parser.ElementTypes.ContainsKey(name.ToUpperInvariant())) Then
'*
'* Gets the type of the element
'*
Dim type = Parser.ElementTypes(name.ToUpperInvariant()).Type
'*
'* Check if we have a different type to create
'*
If (Parser.ElementTypes.ContainsKey(name.ToUpperInvariant())) Then
'*
'* Gets the type of the element
'*
Dim type = Parser.ElementTypes(name.ToUpperInvariant()).Type
'*
'* Check if the type IS BBCodeElement
'*
If (type.Equals(GetType(BBCodeElement))) Then
el = New BBCodeElement()
Else
'*
'* Gets the default constructor
'*
Dim ctor = type.GetConstructor(New Type() {})
If (ctor Is Nothing) Then
Throw New InvalidOperationException("The type " & type.FullName & " does not have a default constructor.")
End If
'*
'* Check if the type IS BBCodeElement
'*
If (type.Equals(GetType(BBCodeElement(Of TContext)))) Then
el = New BBCodeElement(Of TContext)()
Else
'*
'* Gets the default constructor
'*
Dim ctor = type.GetConstructor(New Type() {})
If (ctor Is Nothing) Then
Throw New InvalidOperationException("The type " & type.FullName & " does not have a default constructor.")
End If
'*
'* Creates the new element.
'*
el = TryCast(ctor.Invoke(New Object() {}), BBCodeElement)
If (el Is Nothing) Then
Throw New InvalidOperationException("The type " & type.FullName & " could not be assingned to BBCodeElement.")
End If
End If
Else
el = New BBCodeElement()
End If
'*
'* Creates the new element.
'*
el = TryCast(ctor.Invoke(New Object() {}), BBCodeElement(Of TContext))
If (el Is Nothing) Then
Throw New InvalidOperationException("The type " & type.FullName & " could not be assingned to BBCodeElement.")
End If
End If
Else
el = New BBCodeElement(Of TContext)()
End If
'*
'* Set the element properties
'*
el.SetName(name)
el.SetParser(Parser)
For Each attr In attributes
el.Attributes.Add(attr.Key, attr.Value)
Next
'*
'* Set the element properties
'*
el.SetName(name)
el.SetParser(Parser)
For Each attr In attributes
el.Attributes.Add(attr.Key, attr.Value)
Next
'*
'* Returns the created element.
'*
Return el
'*
'* Returns the created element.
'*
Return el
End Function
End Function
End Class

@ -24,95 +24,95 @@ Imports System.Diagnostics.CodeAnalysis
''' </summary>
<Serializable()> _
<XmlRoot(ElementName:=STR_BBCodeElementTypesXmlElement, [Namespace]:=STR_BBCodeSchemaNamespace)> _
Public NotInheritable Class BBCodeElementTypeDictionary
Inherits Dictionary(Of String, BBCodeElementTypeDefinition)
Implements IXmlSerializable
Private Const STR_ConfigurationItem As String = "element"
''' <summary>Initializes an instance of the <see cref="BBCodeElementTypeDictionary" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes a new instance of the <see cref="BBCodeElementDictionary" /> class with serialized data.</summary>
''' <param name="info">A <see cref="T:System.Runtime.Serialization.SerializationInfo" /> object containing the information required to serialize the <see cref="T:System.Collections.Generic.Dictionary`2" />.</param>
''' <param name="context">A <see cref="T:System.Runtime.Serialization.StreamingContext" /> structure containing the source and destination of the serialized stream associated with the <see cref="T:System.Collections.Generic.Dictionary`2" />.</param>
Private Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
End Sub
''' <summary>
''' Adds the specified key and value to the dictionary.
''' </summary>
''' <param name="tagName">The key of the element to add.</param>
''' <param name="value">The value of the element to add.</param>
Private Shadows Sub Add(ByVal tagName As String, ByVal value As BBCodeElementTypeDefinition)
ValidateTagName(tagName)
ValidateBBCodeElementType(value.Type)
MyBase.Add(tagName.ToUpperInvariant(), value)
End Sub
''' <summary>
''' Adds the specified key and value to the dictionary.
''' </summary>
''' <param name="tagName">The key of the element to add.</param>
''' <param name="value">The value of the element to add.</param>
Public Shadows Sub Add(ByVal tagName As String, ByVal value As Type, ByVal requireClosingTag As Boolean)
Add(tagName.ToUpperInvariant(), New BBCodeElementTypeDefinition() With {.TagName = tagName, .Type = value, .RequireClosingTag = requireClosingTag})
End Sub
''' <summary>This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute" /> to the class.</summary>
''' <returns>An <see cref="T:System.Xml.Schema.XmlSchema" /> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)" /> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)" /> method.</returns>
Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
Return Nothing
End Function
''' <summary>Generates an object from its XML representation.</summary>
''' <param name="reader">The <see cref="T:System.Xml.XmlReader" /> stream from which the object is deserialized.</param>
Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
'*
'* Check the name of the element
'*
If (reader.NamespaceURI <> STR_BBCodeSchemaNamespace) OrElse (reader.LocalName <> STR_BBCodeElementTypesXmlElement) Then
Exit Sub
End If
'*
'* Reads the items
'*
Do While (reader.Read() AndAlso reader.LocalName = STR_ConfigurationItem AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace)
Dim definition As New BBCodeElementTypeDefinition()
With definition
.TagName = reader.GetAttribute("name")
Boolean.TryParse(reader.GetAttribute("requireClosingTag"), .RequireClosingTag)
.Type = System.Type.GetType(reader.GetAttribute("type"))
End With
If (definition.Type.IsSubclassOf(GetType(BBCodeElement))) Then
Me.Add(definition.TagName, definition)
End If
Loop
If (reader.NodeType = Xml.XmlNodeType.EndElement) Then
reader.Read()
End If
End Sub
''' <summary>Converts an object into its XML representation.</summary>
''' <param name="writer">The <see cref="T:System.Xml.XmlWriter" /> stream to which the object is serialized.</param>
<SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", justification:="For human legibility purposes the tagname must be lower case in the configuration file.")> _
Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
For Each it In Me
writer.WriteStartElement(STR_ConfigurationItem, STR_BBCodeSchemaNamespace)
writer.WriteAttributeString("name", it.Key.ToLower(CultureInfo.InvariantCulture))
writer.WriteAttributeString("requireClosingTag", it.Value.RequireClosingTag.ToString())
writer.WriteAttributeString("type", it.Value.Type.AssemblyQualifiedName)
writer.WriteEndElement()
Next
End Sub
Public NotInheritable Class BBCodeElementTypeDictionary(Of TContext As Class)
Inherits Dictionary(Of String, BBCodeElementTypeDefinition)
Implements IXmlSerializable
Private Const STR_ConfigurationItem As String = "element"
''' <summary>Initializes an instance of the <see cref="BBCodeElementTypeDictionary" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes a new instance of the <see cref="BBCodeElementDictionary" /> class with serialized data.</summary>
''' <param name="info">A <see cref="T:System.Runtime.Serialization.SerializationInfo" /> object containing the information required to serialize the <see cref="T:System.Collections.Generic.Dictionary`2" />.</param>
''' <param name="context">A <see cref="T:System.Runtime.Serialization.StreamingContext" /> structure containing the source and destination of the serialized stream associated with the <see cref="T:System.Collections.Generic.Dictionary`2" />.</param>
Private Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
End Sub
''' <summary>
''' Adds the specified key and value to the dictionary.
''' </summary>
''' <param name="tagName">The key of the element to add.</param>
''' <param name="value">The value of the element to add.</param>
Private Shadows Sub Add(ByVal tagName As String, ByVal value As BBCodeElementTypeDefinition)
ValidateTagName(tagName)
ValidateBBCodeElementType(Of TContext)(value.Type)
MyBase.Add(tagName.ToUpperInvariant(), value)
End Sub
''' <summary>
''' Adds the specified key and value to the dictionary.
''' </summary>
''' <param name="tagName">The key of the element to add.</param>
''' <param name="value">The value of the element to add.</param>
Public Shadows Sub Add(ByVal tagName As String, ByVal value As Type, ByVal requireClosingTag As Boolean)
Add(tagName.ToUpperInvariant(), New BBCodeElementTypeDefinition() With {.TagName = tagName, .Type = value, .RequireClosingTag = requireClosingTag})
End Sub
''' <summary>This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute" /> to the class.</summary>
''' <returns>An <see cref="T:System.Xml.Schema.XmlSchema" /> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)" /> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)" /> method.</returns>
Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
Return Nothing
End Function
''' <summary>Generates an object from its XML representation.</summary>
''' <param name="reader">The <see cref="T:System.Xml.XmlReader" /> stream from which the object is deserialized.</param>
Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml
'*
'* Check the name of the element
'*
If (reader.NamespaceURI <> STR_BBCodeSchemaNamespace) OrElse (reader.LocalName <> STR_BBCodeElementTypesXmlElement) Then
Exit Sub
End If
'*
'* Reads the items
'*
Do While (reader.Read() AndAlso reader.LocalName = STR_ConfigurationItem AndAlso reader.NamespaceURI = STR_BBCodeSchemaNamespace)
Dim definition As New BBCodeElementTypeDefinition()
With definition
.TagName = reader.GetAttribute("name")
Boolean.TryParse(reader.GetAttribute("requireClosingTag"), .RequireClosingTag)
.Type = System.Type.GetType(reader.GetAttribute("type"))
End With
If (definition.Type.IsSubclassOf(GetType(BBCodeElement(Of TContext)))) Then
Me.Add(definition.TagName, definition)
End If
Loop
If (reader.NodeType = Xml.XmlNodeType.EndElement) Then
reader.Read()
End If
End Sub
''' <summary>Converts an object into its XML representation.</summary>
''' <param name="writer">The <see cref="T:System.Xml.XmlWriter" /> stream to which the object is serialized.</param>
<SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", justification:="For human legibility purposes the tagname must be lower case in the configuration file.")> _
Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml
For Each it In Me
writer.WriteStartElement(STR_ConfigurationItem, STR_BBCodeSchemaNamespace)
writer.WriteAttributeString("name", it.Key.ToLower(CultureInfo.InvariantCulture))
writer.WriteAttributeString("requireClosingTag", it.Value.RequireClosingTag.ToString())
writer.WriteAttributeString("type", it.Value.Type.AssemblyQualifiedName)
writer.WriteEndElement()
Next
End Sub
End Class

@ -18,84 +18,84 @@
''' <summary>
''' Represents the basic node of an BBCode document.
''' </summary>
Public MustInherit Class BBCodeNode
Public MustInherit Class BBCodeNode(Of TContext As Class)
Private __Parent As BBCodeNode
Private __Parser As BBCodeParser
Private __Parent As BBCodeNode(Of TContext)
Private __Parser As BBCodeParser(Of TContext)
''' <summary>Initializes an instance of the <see cref="BBCodeNode" /> class.
''' This is the default constructor for this class.</summary>
Protected Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNode" /> class.
''' This is the default constructor for this class.</summary>
Protected Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNode" /> class.</summary>
''' <param name="parser">The parser used to create this element.</param>
Protected Sub New(ByVal parser As BBCodeParser)
__Parser = parser
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNode" /> class.</summary>
''' <param name="parser">The parser used to create this element.</param>
Protected Sub New(ByVal parser As BBCodeParser(Of TContext))
__Parser = parser
End Sub
''' <summary>
''' Gets the parent node.
''' </summary>
Public ReadOnly Property Parent() As BBCodeNode
Get
Return __Parent
End Get
End Property
''' <summary>
''' Gets the parent node.
''' </summary>
Public ReadOnly Property Parent() As BBCodeNode(Of TContext)
Get
Return __Parent
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that create this instance of the <see cref="BBCodeNode"/>.
''' </summary>
Protected Friend ReadOnly Property Parser() As BBCodeParser
Get
Return __Parser
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeParser"/> that create this instance of the <see cref="BBCodeNode"/>.
''' </summary>
Protected Friend ReadOnly Property Parser() As BBCodeParser(Of TContext)
Get
Return __Parser
End Get
End Property
''' <summary>
''' When implemented in a derived class, transforms this instance of <see cref="BBCodeNode"/> into its desired text representation.
''' </summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter"/> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter"/>.</returns>
Public MustOverride Function Format(ByVal formatter As ITextFormatter) As String
''' <summary>
''' When implemented in a derived class, transforms this instance of <see cref="BBCodeNode"/> into its desired text representation.
''' </summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter"/> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter"/>.</returns>
Public MustOverride Function Format(ByVal context As TContext, ByVal formatter As ITextFormatter) As String
''' <summary>
''' When implemented in a derived class, gets or sets the inner BBCode.
''' </summary>
''' <value>The BBCode between the start and end tags.</value>
Public MustOverride Property InnerBBCode() As String
''' <summary>
''' When implemented in a derived class, gets or sets the inner BBCode.
''' </summary>
''' <value>The BBCode between the start and end tags.</value>
Public MustOverride Property InnerBBCode() As String
''' <summary>
''' When implemented in a derived class, gets the outer BBCode.
''' </summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode"/>.</value>
Public MustOverride ReadOnly Property OuterBBCode() As String
''' <summary>
''' When implemented in a derived class, gets the outer BBCode.
''' </summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode"/>.</value>
Public MustOverride ReadOnly Property OuterBBCode() As String
''' <summary>
''' When implemented in a derived class, gets or sets the plain text of the node.
''' </summary>
''' <value>The plain text between the start and end tags.</value>
Public MustOverride Property InnerText() As String
''' <summary>
''' When implemented in a derived class, gets or sets the plain text of the node.
''' </summary>
''' <value>The plain text between the start and end tags.</value>
Public MustOverride Property InnerText() As String
''' <summary>
''' Sets the <see cref="BBCodeParser"/> of this instance.
''' </summary>
''' <param name="parser">The new parser of this instance.</param>
Friend Sub SetParser(ByVal parser As BBCodeParser)
__Parser = parser
End Sub
''' <summary>
''' Sets the <see cref="BBCodeParser"/> of this instance.
''' </summary>
''' <param name="parser">The new parser of this instance.</param>
Friend Sub SetParser(ByVal parser As BBCodeParser(Of TContext))
__Parser = parser
End Sub
''' <summary>
''' The the parent node of this instance of the <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="parentNode">The parent node.</param>
Protected Friend Sub SetParent(ByVal parentNode As BBCodeNode)
Dim element = TryCast(parentNode, BBCodeElement)
If (element Is Nothing) OrElse (String.IsNullOrEmpty(element.Name)) Then
__Parent = Nothing
Else
__Parent = element
End If
End Sub
''' <summary>
''' The the parent node of this instance of the <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="parentNode">The parent node.</param>
Protected Friend Sub SetParent(ByVal parentNode As BBCodeNode(Of TContext))
Dim element = TryCast(parentNode, BBCodeElement(Of TContext))
If (element Is Nothing) OrElse (String.IsNullOrEmpty(element.Name)) Then
__Parent = Nothing
Else
__Parent = element
End If
End Sub
End Class

@ -18,78 +18,78 @@
''' <summary>
''' Represents a collection of <see cref="BBCodeNode"/>.
''' </summary>
Public Class BBCodeNodeCollection
Inherits ObjectModel.Collection(Of BBCodeNode)
Public Class BBCodeNodeCollection(Of TContext As Class)
Inherits ObjectModel.Collection(Of BBCodeNode(Of TContext))
Private __Owner As BBCodeNode
Private __Owner As BBCodeNode(Of TContext)
''' <summary>Initializes an instance of the <see cref="BBCodeNodeCollection" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNodeCollection" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNodeCollection" /> class.</summary>
''' <param name="owner">The collection owner.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="owner" /> is <langword name="null" />.</exception>
Friend Sub New(ByVal owner As BBCodeNode)
If (owner Is Nothing) Then
Throw New ArgumentNullException("owner")
End If
__Owner = owner
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeNodeCollection" /> class.</summary>
''' <param name="owner">The collection owner.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="owner" /> is <langword name="null" />.</exception>
Friend Sub New(ByVal owner As BBCodeNode(Of TContext))
If (owner Is Nothing) Then
Throw New ArgumentNullException("owner")
End If
__Owner = owner
End Sub
''' <summary>
''' Gets or sets the owner of the collection.
''' </summary>
Friend ReadOnly Property Owner() As BBCodeNode
Get
Return __Owner
End Get
End Property
''' <summary>
''' Gets or sets the owner of the collection.
''' </summary>
Friend ReadOnly Property Owner() As BBCodeNode(Of TContext)
Get
Return __Owner
End Get
End Property
''' <summary>Adds an object to the end of the <see cref="BBCodeNodeCollection" />.</summary>
''' <param name="node">The object to be added to the end of the <see cref="BBCodeNodeCollection" />.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="node" /> is <langword name="null" />.</exception>
Public Shadows Sub Add(ByVal node As BBCodeNode)
If (node Is Nothing) Then
Throw New ArgumentNullException("node")
End If
node.SetParent(Me.Owner)
MyBase.Add(node)
End Sub
''' <summary>Adds an object to the end of the <see cref="BBCodeNodeCollection" />.</summary>
''' <param name="node">The object to be added to the end of the <see cref="BBCodeNodeCollection" />.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="node" /> is <langword name="null" />.</exception>
Public Shadows Sub Add(ByVal node As BBCodeNode(Of TContext))
If (node Is Nothing) Then
Throw New ArgumentNullException("node")
End If
node.SetParent(Me.Owner)
MyBase.Add(node)
End Sub
''' <summary>Adds the elements of the specified collection to the end of the <see cref="BBCodeNodeCollection" />.</summary>
''' <param name="collection">The collection whose elements should be added to the end of the <see cref="BBCodeNodeCollection" />.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="collection" /> is <langword name="null" />.</exception>
Public Shadows Sub AddRange(ByVal collection As IEnumerable(Of BBCodeNode))
If (collection Is Nothing) Then
Throw New ArgumentNullException("collection")
End If
For Each n In collection
Me.Add(n)
Next
End Sub
''' <summary>Adds the elements of the specified collection to the end of the <see cref="BBCodeNodeCollection" />.</summary>
''' <param name="collection">The collection whose elements should be added to the end of the <see cref="BBCodeNodeCollection" />.</param>
''' <exception cref="ArgumentNullException">The argument <paramref name="collection" /> is <langword name="null" />.</exception>
Public Shadows Sub AddRange(ByVal collection As IEnumerable(Of BBCodeNode(Of TContext)))
If (collection Is Nothing) Then
Throw New ArgumentNullException("collection")
End If
For Each n In collection
Me.Add(n)
Next
End Sub
''' <summary>
''' Inserts an element into the <see cref="BBCodeNodeCollection" /> at the specified index.
''' </summary>
''' <param name="index">The zero-based index at which item should be inserted.</param>
''' <param name="node">The object to insert.</param>
Public Shadows Sub Insert(ByVal index As Integer, ByVal node As BBCodeNode)
node.SetParent(Me.Owner)
MyBase.Insert(index, node)
End Sub
''' <summary>
''' Inserts an element into the <see cref="BBCodeNodeCollection" /> at the specified index.
''' </summary>
''' <param name="index">The zero-based index at which item should be inserted.</param>
''' <param name="node">The object to insert.</param>
Public Shadows Sub Insert(ByVal index As Integer, ByVal node As BBCodeNode(Of TContext))
node.SetParent(Me.Owner)
MyBase.Insert(index, node)
End Sub
''' <summary>
''' Inserts the elements of a collection into the <see cref="BBCodeNodeCollection" /> at the specified index.
''' </summary>
''' <param name="index">The zero-based index at which item should be inserted.</param>
''' <param name="collection">The collection whose elements should be inserted into the <see cref="BBCodeNodeCollection" />.</param>
Public Shadows Sub InsertRange(ByVal index As Integer, ByVal collection As IEnumerable(Of BBCodeNode))
For Each node In collection
node.SetParent(Me.Owner)
Next
MyBase.Insert(index, collection)
End Sub
''' <summary>
''' Inserts the elements of a collection into the <see cref="BBCodeNodeCollection" /> at the specified index.
''' </summary>
''' <param name="index">The zero-based index at which item should be inserted.</param>
''' <param name="collection">The collection whose elements should be inserted into the <see cref="BBCodeNodeCollection" />.</param>
Public Shadows Sub InsertRange(ByVal index As Integer, ByVal collection As IEnumerable(Of BBCodeNode(Of TContext)))
For Each node In collection
node.SetParent(Me.Owner)
Next
MyBase.Insert(index, collection)
End Sub
End Class

@ -21,320 +21,320 @@ Imports System.Diagnostics.CodeAnalysis
''' <summary>
''' The parser of
''' </summary>
Public NotInheritable Class BBCodeParser
Private __Factory As BBCodeElementFactory
Private __Configuration As BBCodeConfiguration
Private Shared ReadOnly __ConfigSerializer As New System.Xml.Serialization.XmlSerializer(GetType(BBCodeConfiguration))
Private Shared ReadOnly __Tokenizer As Tokenization.Tokenizer = PrepareTokenizer()
''' <summary>Initializes an instance of the <see cref="BBCodeParser" /> class.
''' This is the default constructor for this class.</summary>
Public Sub New()
End Sub
''' <summary>
''' Gets the dictionary of elements to be replaced by the <see cref="BBCodeParser"/>.
''' </summary>
Public ReadOnly Property Dictionary() As BBCodeElementDictionary
Get
If (__Configuration Is Nothing) Then
__Configuration = New BBCodeConfiguration()
End If
Return __Configuration.Dictionary
End Get
End Property
''' <summary>
''' Gets the dictionary of types created by the parser.
''' </summary>
Public ReadOnly Property ElementTypes() As BBCodeElementTypeDictionary
Get
If (__Configuration Is Nothing) Then
__Configuration = New BBCodeConfiguration()
End If
Return __Configuration.ElementTypes
End Get
End Property
Public NotInheritable Class BBCodeParser(Of TContext As Class)
Private __Factory As BBCodeElementFactory(Of TContext)
Private __Configuration As BBCodeConfiguration(Of TContext)
Private Shared ReadOnly __ConfigSerializer As New System.Xml.Serialization.XmlSerializer(GetType(BBCodeConfiguration(Of TContext)))
Private Shared ReadOnly __Tokenizer As Tokenization.Tokenizer = PrepareTokenizer()
''' <summary>Initializes an instance of the <see cref="BBCodeParser" /> class.
''' This is the default constructor for this class.</summary>
Public Sub New()
End Sub
''' <summary>
''' Gets the dictionary of elements to be replaced by the <see cref="BBCodeParser"/>.
''' </summary>
Public ReadOnly Property Dictionary() As BBCodeElementDictionary
Get
If (__Configuration Is Nothing) Then
__Configuration = New BBCodeConfiguration(Of TContext)()
End If
Return __Configuration.Dictionary
End Get
End Property
''' <summary>
''' Gets the dictionary of types created by the parser.
''' </summary>
Public ReadOnly Property ElementTypes() As BBCodeElementTypeDictionary(Of TContext)
Get
If (__Configuration Is Nothing) Then
__Configuration = New BBCodeConfiguration(Of TContext)()
End If
Return __Configuration.ElementTypes
End Get
End Property
#Region " LoadConfiguration Methods "
''' <summary>
''' Loads the configuration from the specified filename.
''' </summary>
''' <param name="fileName">The name of the file to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal fileName As String)
If (String.IsNullOrEmpty(fileName)) Then
Throw New ArgumentNullException("fileName")
End If
Using fileStream As New IO.FileStream(fileName, IO.FileMode.Open)
LoadConfiguration(fileStream)
End Using
End Sub
''' <summary>
''' Loads the configuration from the specified <see cref="IO.Stream"/>.
''' </summary>
''' <param name="stream">A <see cref="IO.Stream"/> to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal stream As IO.Stream)
LoadConfiguration(New IO.StreamReader(stream, Text.Encoding.UTF8, True))
End Sub
''' <summary>
''' Loads the configuration from the specified <see cref="IO.TextReader"/>.
''' </summary>
''' <param name="reader">The <see cref="IO.TextReader"/> to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal reader As IO.TextReader)
Dim dic = __ConfigSerializer.Deserialize(reader)
If (dic IsNot Nothing) Then
__Configuration = dic
End If
End Sub
''' <summary>
''' Loads the configuration from the specified filename.
''' </summary>
''' <param name="fileName">The name of the file to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal fileName As String)
If (String.IsNullOrEmpty(fileName)) Then
Throw New ArgumentNullException("fileName")
End If
Using fileStream As New IO.FileStream(fileName, IO.FileMode.Open)
LoadConfiguration(fileStream)
End Using
End Sub
''' <summary>
''' Loads the configuration from the specified <see cref="IO.Stream"/>.
''' </summary>
''' <param name="stream">A <see cref="IO.Stream"/> to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal stream As IO.Stream)
LoadConfiguration(New IO.StreamReader(stream, Text.Encoding.UTF8, True))
End Sub
''' <summary>
''' Loads the configuration from the specified <see cref="IO.TextReader"/>.
''' </summary>
''' <param name="reader">The <see cref="IO.TextReader"/> to read the dictionary from.</param>
Public Sub LoadConfiguration(ByVal reader As IO.TextReader)
Dim dic = __ConfigSerializer.Deserialize(reader)
If (dic IsNot Nothing) Then
__Configuration = dic
End If
End Sub
#End Region
#Region " SaveConfiguration Methods "
''' <summary>
''' Saves the conficuration to the specified file.
''' </summary>
''' <param name="fileName">The name of the file to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal fileName As String)
If (String.IsNullOrEmpty(fileName)) Then
Throw New ArgumentNullException("fileName")
End If
Using fileStream As New IO.FileStream(fileName, IO.FileMode.Create)
SaveConfiguration(fileStream)
End Using
End Sub
''' <summary>
''' Saves the conficuration to the specified <see cref="IO.Stream"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal stream As IO.Stream)
SaveConfiguration(New IO.StreamWriter(stream, Text.Encoding.UTF8))
End Sub
''' <summary>
''' Saves the conficuration to the specified <see cref="IO.TextWriter"/>.
''' </summary>
''' <param name="writer">The <see cref="IO.TextWriter"/> to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal writer As IO.TextWriter)
__ConfigSerializer.Serialize(writer, __Configuration)
End Sub
''' <summary>
''' Saves the conficuration to the specified file.
''' </summary>
''' <param name="fileName">The name of the file to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal fileName As String)
If (String.IsNullOrEmpty(fileName)) Then
Throw New ArgumentNullException("fileName")
End If
Using fileStream As New IO.FileStream(fileName, IO.FileMode.Create)
SaveConfiguration(fileStream)
End Using
End Sub
''' <summary>
''' Saves the conficuration to the specified <see cref="IO.Stream"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal stream As IO.Stream)
SaveConfiguration(New IO.StreamWriter(stream, Text.Encoding.UTF8))
End Sub
''' <summary>
''' Saves the conficuration to the specified <see cref="IO.TextWriter"/>.
''' </summary>
''' <param name="writer">The <see cref="IO.TextWriter"/> to save the dictionary.</param>
Public Sub SaveConfiguration(ByVal writer As IO.TextWriter)
__ConfigSerializer.Serialize(writer, __Configuration)
End Sub
#End Region
#Region " Parse Methods "
''' <summary>
''' Parses the specified text, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="text">The text to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed text.</returns>
Public Function Parse(ByVal text As String) As BBCodeDocument
Using reader As New IO.StringReader(text)
Return Parse(reader)
End Using
End Function
''' <summary>
''' Parses the specified stream, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.Stream"/>.</returns>
Public Function Parse(ByVal stream As IO.Stream) As BBCodeDocument
Return Parse(stream, Text.Encoding.UTF8)
End Function
''' <summary>
''' Parses the specified stream, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to be parsed.</param>
''' <param name="encoding">The encoding of the stream.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.Stream"/>.</returns>
Public Function Parse(ByVal stream As IO.Stream, ByVal encoding As Text.Encoding) As BBCodeDocument
Return Parse(New IO.StreamReader(stream, encoding))
End Function
''' <summary>
''' Parses the specified <see cref="IO.TextReader"/>, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="reader">The <see cref="IO.TextReader"/> to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.TextReader"/>.</returns>
Public Function Parse(ByVal reader As IO.TextReader) As BBCodeDocument
Dim doc = New BBCodeDocument(Me)
Dim rootElement As New BBCodeElement(Me)
Dim currentElement As BBCodeElement = rootElement
Dim tk As Tokenization.Token
Dim sb As New Text.StringBuilder()
Dim sbText As New Text.StringBuilder()
Do While (reader.Peek() <> -1)
Dim line As String = reader.ReadLine() & vbCrLf
sbText.AppendLine(line)
Do
'*
'* Get the next token
'*
tk = Tokenizer.GetToken(line)
If (tk Is Nothing) Then
Exit Do
End If
Dim tag = New BBCodeTag(tk.Value)
ParseElement(rootElement, currentElement, tk, sb, tag)
Loop
Loop
'*
'* Add the text node
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(sb.ToString()))
End If
'*
'* Add the nodes to the document
'*
doc.Nodes.AddRange(rootElement.Nodes)
'*
'* Sets the source text
'*
doc.SetText(sbText.ToString())
Return doc
End Function
''' <summary>
''' Parses the specified text, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="text">The text to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed text.</returns>
Public Function Parse(ByVal text As String) As BBCodeDocument(Of TContext)
Using reader As New IO.StringReader(text)
Return Parse(reader)
End Using
End Function
''' <summary>
''' Parses the specified stream, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.Stream"/>.</returns>
Public Function Parse(ByVal stream As IO.Stream) As BBCodeDocument(Of TContext)
Return Parse(stream, Text.Encoding.UTF8)
End Function
''' <summary>
''' Parses the specified stream, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="stream">The <see cref="IO.Stream"/> to be parsed.</param>
''' <param name="encoding">The encoding of the stream.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.Stream"/>.</returns>
Public Function Parse(ByVal stream As IO.Stream, ByVal encoding As Text.Encoding) As BBCodeDocument(Of TContext)
Return Parse(New IO.StreamReader(stream, encoding))
End Function
''' <summary>
''' Parses the specified <see cref="IO.TextReader"/>, returning a collection of <see cref="BBCodeNode"/>.
''' </summary>
''' <param name="reader">The <see cref="IO.TextReader"/> to be parsed.</param>
''' <returns>A <see cref="BBCodeNodeCollection"/> containing the parsed <see cref="IO.TextReader"/>.</returns>
Public Function Parse(ByVal reader As IO.TextReader) As BBCodeDocument(Of TContext)
Dim doc = New BBCodeDocument(Of TContext)(Me)
Dim rootElement As New BBCodeElement(Of TContext)(Me)
Dim currentElement As BBCodeElement(Of TContext) = rootElement
Dim tk As Tokenization.Token
Dim sb As New Text.StringBuilder()
Dim sbText As New Text.StringBuilder()
Do While (reader.Peek() <> -1)
Dim line As String = reader.ReadLine() & vbCrLf
sbText.AppendLine(line)
Do
'*
'* Get the next token
'*
tk = Tokenizer.GetToken(line)
If (tk Is Nothing) Then
Exit Do
End If
Dim tag = New BBCodeTag(tk.Value)
ParseElement(rootElement, currentElement, tk, sb, tag)
Loop
Loop
'*
'* Add the text node
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(Of TContext)(sb.ToString()))
End If
'*
'* Add the nodes to the document
'*
doc.Nodes.AddRange(rootElement.Nodes)
'*
'* Sets the source text
'*
doc.SetText(sbText.ToString())
Return doc
End Function
#End Region
''' <summary>
''' Gets the <see cref="Tokenization.Tokenizer"/>.
''' </summary>
Private Shared ReadOnly Property Tokenizer() As Tokenization.Tokenizer
Get
Return __Tokenizer
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeElementFactory"/>.
''' </summary>
Private ReadOnly Property Factory() As BBCodeElementFactory
Get
If (__Factory Is Nothing) Then
__Factory = New BBCodeElementFactory(Me)
End If
Return __Factory
End Get
End Property
Private Sub ParseElement(ByVal rootElement As BBCodeElement, ByRef currentElement As BBCodeElement, ByVal token As Tokenization.Token, ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Check the token Type
'*
Select Case token.RuleType
Case 0, -1
'*
'* Empty tag or char
'*
sb.Append(token.Value)
Case 1
'*
'* Closing tag
'*
ParseClosingTag(rootElement, currentElement, token, sb, tag)
Case 2, 3, 4
'*
'* Value Tag, Parametrized Tag, Generic Tag
'*
ParseTag(currentElement, sb, tag)
End Select
End Sub
Private Sub ParseTag(ByRef currentElement As BBCodeElement, ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Add the text previous to the current element
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(sb.ToString()))
sb.Remove(0, sb.Length)
End If
'*
'* Add the new element to the list of nodes
'*
Dim el = Factory.CreateElement(tag.Name, tag.Paramters)
currentElement.Nodes.Add(el)
'*
'* Change the current element, if it requires an closing tag
'*
If (el.RequireClosingTag) Then
currentElement = el
End If
End Sub
Private Shared Sub ParseClosingTag(ByVal rootElement As BBCodeElement, ByRef currentElement As BBCodeElement, ByVal token As Tokenization.Token, ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Check if the closing tag is closing a previously open tag
'*
If currentElement.RequireClosingTag AndAlso (String.CompareOrdinal(currentElement.Name, tag.Name) = 0) Then
'*
'* Add the inner text
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(sb.ToString()))
sb.Remove(0, sb.Length)
End If
'*
'* Move up a level
'*
currentElement = If(currentElement.Parent, rootElement)
Else
'*
'* Adds to the text
'*
sb.Append(token.Value)
End If
End Sub
Private Shared Function PrepareTokenizer() As Tokenization.Tokenizer
Dim tk As New Tokenization.Tokenizer
'*
'* Prepares the BBCode Grammar
'*
With tk
'*
'* Define the grammar macros
'*
AddTokenizerBaseMacros(tk)
'*
'* Define the grammar rules
'*
.AddRule("EmptyTag", 0, "\[{w}\]")
.AddRule("ClosingTag", 1, "\[/{name}\]")
.AddRule("ValueTag", 2, "\[{param}\]")
.AddRule("ParamsTag", 3, "\[{name}{params}\]")
.AddRule("Tag", 4, "\[[^ \t\r\n\f\]]+?\]")
.AddRule("Char", -1, ".")
End With
Return tk
End Function
''' <summary>
''' Gets the <see cref="Tokenization.Tokenizer"/>.
''' </summary>
Private Shared ReadOnly Property Tokenizer() As Tokenization.Tokenizer
Get
Return __Tokenizer
End Get
End Property
''' <summary>
''' Gets the <see cref="BBCodeElementFactory"/>.
''' </summary>
Private ReadOnly Property Factory() As BBCodeElementFactory(Of TContext)
Get
If (__Factory Is Nothing) Then
__Factory = New BBCodeElementFactory(Of TContext)(Me)
End If
Return __Factory
End Get
End Property
Private Sub ParseElement(ByVal rootElement As BBCodeElement(Of TContext), ByRef currentElement As BBCodeElement(Of TContext), ByVal token As Tokenization.Token, ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Check the token Type
'*
Select Case token.RuleType
Case 0, -1
'*
'* Empty tag or char
'*
sb.Append(token.Value)
Case 1
'*
'* Closing tag
'*
ParseClosingTag(rootElement, currentElement, token, sb, tag)
Case 2, 3, 4
'*
'* Value Tag, Parametrized Tag, Generic Tag
'*
ParseTag(currentElement, sb, tag)
End Select
End Sub
Private Sub ParseTag(ByRef currentElement As BBCodeElement(Of TContext), ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Add the text previous to the current element
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(Of TContext)(sb.ToString()))
sb.Remove(0, sb.Length)
End If
'*
'* Add the new element to the list of nodes
'*
Dim el = Factory.CreateElement(tag.Name, tag.Paramters)
currentElement.Nodes.Add(el)
'*
'* Change the current element, if it requires an closing tag
'*
If (el.RequireClosingTag) Then
currentElement = el
End If
End Sub
Private Shared Sub ParseClosingTag(ByVal rootElement As BBCodeElement(Of TContext), ByRef currentElement As BBCodeElement(Of TContext), ByVal token As Tokenization.Token, ByVal sb As Text.StringBuilder, ByVal tag As BBCodeTag)
'*
'* Check if the closing tag is closing a previously open tag
'*
If currentElement.RequireClosingTag AndAlso (String.CompareOrdinal(currentElement.Name, tag.Name) = 0) Then
'*
'* Add the inner text
'*
If (sb.Length > 0) Then
currentElement.Nodes.Add(New BBCodeText(Of TContext)(sb.ToString()))
sb.Remove(0, sb.Length)
End If
'*
'* Move up a level
'*
currentElement = If(currentElement.Parent, rootElement)
Else
'*
'* Adds to the text
'*
sb.Append(token.Value)
End If
End Sub
Private Shared Function PrepareTokenizer() As Tokenization.Tokenizer
Dim tk As New Tokenization.Tokenizer
'*
'* Prepares the BBCode Grammar
'*
With tk
'*
'* Define the grammar macros
'*
AddTokenizerBaseMacros(tk)
'*
'* Define the grammar rules
'*
.AddRule("EmptyTag", 0, "\[{w}\]")
.AddRule("ClosingTag", 1, "\[/{name}\]")
.AddRule("ValueTag", 2, "\[{param}\]")
.AddRule("ParamsTag", 3, "\[{name}{params}\]")
.AddRule("Tag", 4, "\[[^ \t\r\n\f\]]+?\]")
.AddRule("Char", -1, ".")
End With
Return tk
End Function
End Class

@ -18,64 +18,64 @@
''' <summary>
''' Represents a simple text in the BBCode.
''' </summary>
Public NotInheritable Class BBCodeText
Inherits BBCodeNode
Public NotInheritable Class BBCodeText(Of TContext As Class)
Inherits BBCodeNode(Of TContext)
Private __InnerText As String
Private __InnerText As String
''' <summary>Initializes an instance of the <see cref="BBCodeText" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeText" /> class.
''' This is the default constructor for this class.</summary>
Friend Sub New()
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeText" /> class.</summary>
''' <param name="text">The text of the <see cref="BBCodeText"/>.</param>
Friend Sub New(ByVal text As String)
Me.InnerText = text
End Sub
''' <summary>Initializes an instance of the <see cref="BBCodeText" /> class.</summary>
''' <param name="text">The text of the <see cref="BBCodeText"/>.</param>
Friend Sub New(ByVal text As String)
Me.InnerText = text
End Sub
''' <summary>Transforms this instance of <see cref="BBCodeText" /> into its desired text representation.</summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter" /> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter" />.</returns>
Public Overrides Function Format(ByVal formatter As ITextFormatter) As String
Return formatter.Format(__InnerText)
End Function
''' <summary>Transforms this instance of <see cref="BBCodeText" /> into its desired text representation.</summary>
''' <param name="formatter">An object that implements the <see cref="ITextFormatter" /> interface.</param>
''' <returns>The text formatted by the <see cref="ITextFormatter" />.</returns>
Public Overrides Function Format(ByVal context As TContext, ByVal formatter As ITextFormatter) As String
Return formatter.Format(__InnerText)
End Function
''' <summary>Gets or sets the inner BBCode.</summary>
''' <value>The BBCode between the start and end tags.</value>
Public Overrides Property InnerBBCode() As String
Get
Return Me.InnerText
End Get
Set(ByVal value As String)
Me.InnerText = value
End Set
End Property
''' <summary>Gets or sets the inner BBCode.</summary>
''' <value>The BBCode between the start and end tags.</value>
Public Overrides Property InnerBBCode() As String
Get
Return Me.InnerText
End Get
Set(ByVal value As String)
Me.InnerText = value
End Set
End Property
''' <summary>Gets or sets the plain text of the node.</summary>
''' <value>The plain text between the start and end tags.</value>
Public Overrides Property InnerText() As String
Get
Return __InnerText
End Get
Set(ByVal value As String)
__InnerText = value
End Set
End Property
''' <summary>Gets or sets the plain text of the node.</summary>
''' <value>The plain text between the start and end tags.</value>
Public Overrides Property InnerText() As String
Get
Return __InnerText
End Get
Set(ByVal value As String)
__InnerText = value
End Set
End Property
''' <summary>Gets the outer BBCode.</summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode" /> .</value>
Public Overrides ReadOnly Property OuterBBCode() As String
Get
Return Me.InnerText
End Get
End Property
''' <summary>Gets the outer BBCode.</summary>
''' <value>The BBCode of this instance of the <see cref="BBCodeNode" /> .</value>
Public Overrides ReadOnly Property OuterBBCode() As String
Get
Return Me.InnerText
End Get
End Property
''' <summary>Returns a <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.</summary>
''' <returns>A <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.</returns>
''' <filterpriority>2</filterpriority>
Public Overrides Function ToString() As String
Return Me.InnerText
End Function
''' <summary>Returns a <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.</summary>
''' <returns>A <see cref="T:System.String" /> that represents the current <see cref="T:System.Object" />.</returns>
''' <filterpriority>2</filterpriority>
Public Overrides Function ToString() As String
Return Me.InnerText
End Function
End Class

@ -20,392 +20,392 @@ Imports System.Diagnostics.CodeAnalysis
Friend Module Utils
Public Const STR_BBCodeSchemaNamespace As String = "" '= "http://pjondevelopment.50webs.com/schema/bbcode"
Public Const STR_BBCodeDictionaryXmlElement As String = "Dictionary"
Public Const STR_BBCodeElementTypesXmlElement As String = "ElementTypes"
Public Const STR_BBCodeConfigurationXmlElement As String = "Configuration"
Public Const STR_BBCodeSchemaNamespace As String = "" '= "http://pjondevelopment.50webs.com/schema/bbcode"
Public Const STR_BBCodeDictionaryXmlElement As String = "Dictionary"
Public Const STR_BBCodeElementTypesXmlElement As String = "ElementTypes"
Public Const STR_BBCodeConfigurationXmlElement As String = "Configuration"
''' <summary>
''' Returns the specified text between quotes.
''' </summary>
''' <param name="text">The text to be placed between quotes.</param>
''' <returns>The text between quotes.</returns>
Public Function Quote(ByVal text As String) As String
Return "'" & text.Replace("'", "''") & "'"
End Function
''' <summary>
''' Returns the specified text between quotes.
''' </summary>
''' <param name="text">The text to be placed between quotes.</param>
''' <returns>The text between quotes.</returns>
Public Function Quote(ByVal text As String) As String
Return "'" & text.Replace("'", "''") & "'"
End Function
''' <summary>
''' Unquotes the specified text.
''' </summary>
''' <param name="text">The text to be unquoted.</param>
''' <returns>The unquoted text.</returns>
Public Function UnQuote(ByVal text As String) As String
Dim rx As New Text.RegularExpressions.Regex("^(?<quote>'(?<text>(?:''|[^'])*)')|(?<doubleQuote>""(?<text>(?:""""|[^""])*)"")$")
Dim m = rx.Match(text)
If (Not m.Success) Then
Return text
End If
If (m.Groups("quote").Success) Then
Return m.Groups("text").Value.Replace("''", "'")
End If
Return m.Groups("text").Value.Replace("""""", """")
End Function
''' <summary>
''' Unquotes the specified text.
''' </summary>
''' <param name="text">The text to be unquoted.</param>
''' <returns>The unquoted text.</returns>
Public Function UnQuote(ByVal text As String) As String
Dim rx As New Text.RegularExpressions.Regex("^(?<quote>'(?<text>(?:''|[^'])*)')|(?<doubleQuote>""(?<text>(?:""""|[^""])*)"")$")
Dim m = rx.Match(text)
If (Not m.Success) Then
Return text
End If
If (m.Groups("quote").Success) Then
Return m.Groups("text").Value.Replace("''", "'")
End If
Return m.Groups("text").Value.Replace("""""", """")
End Function
''' <summary>
''' Validates the specified tag name.
''' </summary>
''' <param name="tagName">The tagname to be validated.</param>
Public Sub ValidateTagName(ByVal tagName As String)
If (String.IsNullOrEmpty(tagName)) Then
Throw New ArgumentNullException("tagName")
End If
If (tagName.IndexOf("=", StringComparison.Ordinal) <> -1) OrElse (tagName.IndexOf("[", StringComparison.Ordinal) <> -1) OrElse (tagName.IndexOf("]", StringComparison.Ordinal) <> -1) Then
Throw New ArgumentException("Invalid tag name. The tag name cannot contain '=' '[' or ']'.", "tagName")
End If
End Sub
''' <summary>
''' Validates the specified tag name.
''' </summary>
''' <param name="tagName">The tagname to be validated.</param>
Public Sub ValidateTagName(ByVal tagName As String)
If (String.IsNullOrEmpty(tagName)) Then
Throw New ArgumentNullException("tagName")
End If
If (tagName.IndexOf("=", StringComparison.Ordinal) <> -1) OrElse (tagName.IndexOf("[", StringComparison.Ordinal) <> -1) OrElse (tagName.IndexOf("]", StringComparison.Ordinal) <> -1) Then
Throw New ArgumentException("Invalid tag name. The tag name cannot contain '=' '[' or ']'.", "tagName")
End If
End Sub
''' <summary>
''' Validates the specified type to ensure that it is a subclass of <see cref="BBCodeElement"/>.
''' </summary>
''' <param name="value">The <see cref="Type"/> to be validated.</param>
Public Sub ValidateBBCodeElementType(ByVal value As Type)
''' <summary>
''' Validates the specified type to ensure that it is a subclass of <see cref="BBCodeElement"/>.
''' </summary>
''' <param name="value">The <see cref="Type"/> to be validated.</param>
Public Sub ValidateBBCodeElementType(Of TContext As Class)(ByVal value As Type)
'*
'* Validate is nothing
'*
If (value Is Nothing) Then
Throw New ArgumentNullException("value")
End If
'*
'* Validate is nothing
'*
If (value Is Nothing) Then
Throw New ArgumentNullException("value")
End If
'*
'* Validates the BBCodeElement itself
'*
Dim bbcodeType = GetType(BBCodeElement)
If (value.Equals(bbcodeType)) Then
Exit Sub
End If
'*
'* Validates the BBCodeElement itself
'*
Dim bbcodeType = GetType(BBCodeElement(Of TContext))
If (value.Equals(bbcodeType)) Then
Exit Sub
End If
'*
'* Validate subclass
'*
If Not bbcodeType.IsAssignableFrom(value) Then
Throw New InvalidOperationException("The type " & value.FullName & " must be a assingable to BBCodeElement.")
End If
'*
'* Validate subclass
'*
If Not bbcodeType.IsAssignableFrom(value) Then
Throw New InvalidOperationException("The type " & value.FullName & " must be a assingable to BBCodeElement.")
End If
'*
'* Validate default constructor
'*
If (value.GetConstructor(New Type() {}) Is Nothing) Then
Throw New InvalidOperationException("The type " & value.FullName & " does not provide a public default constructor.")
End If
'*
'* Validate default constructor
'*
If (value.GetConstructor(New Type() {}) Is Nothing) Then
Throw New InvalidOperationException("The type " & value.FullName & " does not provide a public default constructor.")
End If
End Sub
End Sub
''' <summary>
''' Encodes the specified text as HTML.
''' </summary>
''' <param name="text">The text to be encoded.</param>
''' <returns>The encoded HTML.</returns>
<SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode", Justification:="This methos is simple a list of substuition character by its HTML representation.")> _
Public Function HtmlEncode(ByVal text As String) As String
Dim sb As New Text.StringBuilder(text)
sb.Replace(ChrW(&H26), "&amp;")
sb.Replace(ChrW(&H22), "&quot;")
sb.Replace(ChrW(&H27), "&apos;")
sb.Replace(ChrW(&H3C), "&lt;")
sb.Replace(ChrW(&H3E), "&gt;")
sb.Replace(ChrW(&HA0), "&nbsp;")
sb.Replace(ChrW(&HA1), "&iexcl;")
sb.Replace(ChrW(&HA2), "&cent;")
sb.Replace(ChrW(&HA3), "&pound;")
sb.Replace(ChrW(&HA4), "&curren;")
sb.Replace(ChrW(&HA5), "&yen;")
sb.Replace(ChrW(&HA6), "&brvbar;")
sb.Replace(ChrW(&HA7), "&sect;")
sb.Replace(ChrW(&HA8), "&uml;")
sb.Replace(ChrW(&HA9), "&copy;")
sb.Replace(ChrW(&HAA), "&ordf;")
sb.Replace(ChrW(&HAB), "&laquo;")
sb.Replace(ChrW(&HAC), "&not;")
sb.Replace(ChrW(&HAD), "&shy;")
sb.Replace(ChrW(&HAE), "&reg;")
sb.Replace(ChrW(&HAF), "&macr;")
sb.Replace(ChrW(&HB0), "&deg;")
sb.Replace(ChrW(&HB1), "&plusmn;")
sb.Replace(ChrW(&HB2), "&sup2;")
sb.Replace(ChrW(&HB3), "&sup3;")
sb.Replace(ChrW(&HB4), "&acute;")
sb.Replace(ChrW(&HB5), "&micro;")
sb.Replace(ChrW(&HB6), "&para;")
sb.Replace(ChrW(&HB7), "&middot;")
sb.Replace(ChrW(&HB8), "&cedil;")
sb.Replace(ChrW(&HB9), "&sup1;")
sb.Replace(ChrW(&HBA), "&ordm;")
sb.Replace(ChrW(&HBB), "&raquo;")
sb.Replace(ChrW(&HBC), "&frac14;")
sb.Replace(ChrW(&HBD), "&frac12;")
sb.Replace(ChrW(&HBE), "&frac34;")
sb.Replace(ChrW(&HBF), "&iquest;")
sb.Replace(ChrW(&HC0), "&Agrave;")
sb.Replace(ChrW(&HC1), "&Aacute;")
sb.Replace(ChrW(&HC2), "&Acirc;")
sb.Replace(ChrW(&HC3), "&Atilde;")
sb.Replace(ChrW(&HC4), "&Auml;")
sb.Replace(ChrW(&HC5), "&Aring;")
sb.Replace(ChrW(&HC6), "&AElig;")
sb.Replace(ChrW(&HC7), "&Ccedil;")
sb.Replace(ChrW(&HC8), "&Egrave;")
sb.Replace(ChrW(&HC9), "&Eacute;")
sb.Replace(ChrW(&HCA), "&Ecirc;")
sb.Replace(ChrW(&HCB), "&Euml;")
sb.Replace(ChrW(&HCC), "&Igrave;")
sb.Replace(ChrW(&HCD), "&Iacute;")
sb.Replace(ChrW(&HCE), "&Icirc;")
sb.Replace(ChrW(&HCF), "&Iuml;")
sb.Replace(ChrW(&HD0), "&ETH;")
sb.Replace(ChrW(&HD1), "&Ntilde;")
sb.Replace(ChrW(&HD2), "&Ograve;")
sb.Replace(ChrW(&HD3), "&Oacute;")
sb.Replace(ChrW(&HD4), "&Ocirc;")
sb.Replace(ChrW(&HD5), "&Otilde;")
sb.Replace(ChrW(&HD6), "&Ouml;")
sb.Replace(ChrW(&HD7), "&times;")
sb.Replace(ChrW(&HD8), "&Oslash;")
sb.Replace(ChrW(&HD9), "&Ugrave;")
sb.Replace(ChrW(&HDA), "&Uacute;")
sb.Replace(ChrW(&HDB), "&Ucirc;")
sb.Replace(ChrW(&HDC), "&Uuml;")
sb.Replace(ChrW(&HDD), "&Yacute;")
sb.Replace(ChrW(&HDE), "&THORN;")
sb.Replace(ChrW(&HDF), "&szlig;")
sb.Replace(ChrW(&HE0), "&agrave;")
sb.Replace(ChrW(&HE1), "&aacute;")
sb.Replace(ChrW(&HE2), "&acirc;")
sb.Replace(ChrW(&HE3), "&atilde;")
sb.Replace(ChrW(&HE4), "&auml;")
sb.Replace(ChrW(&HE5), "&aring;")
sb.Replace(ChrW(&HE6), "&aelig;")
sb.Replace(ChrW(&HE7), "&ccedil;")
sb.Replace(ChrW(&HE8), "&egrave;")
sb.Replace(ChrW(&HE9), "&eacute;")
sb.Replace(ChrW(&HEA), "&ecirc;")
sb.Replace(ChrW(&HEB), "&euml;")
sb.Replace(ChrW(&HEC), "&igrave;")
sb.Replace(ChrW(&HED), "&iacute;")
sb.Replace(ChrW(&HEE), "&icirc;")
sb.Replace(ChrW(&HEF), "&iuml;")
sb.Replace(ChrW(&HF0), "&eth;")
sb.Replace(ChrW(&HF1), "&ntilde;")
sb.Replace(ChrW(&HF2), "&ograve;")
sb.Replace(ChrW(&HF3), "&oacute;")
sb.Replace(ChrW(&HF4), "&ocirc;")
sb.Replace(ChrW(&HF5), "&otilde;")
sb.Replace(ChrW(&HF6), "&ouml;")
sb.Replace(ChrW(&HF7), "&divide;")
sb.Replace(ChrW(&HF8), "&oslash;")
sb.Replace(ChrW(&HF9), "&ugrave;")
sb.Replace(ChrW(&HFA), "&uacute;")
sb.Replace(ChrW(&HFB), "&ucirc;")
sb.Replace(ChrW(&HFC), "&uuml;")
sb.Replace(ChrW(&HFD), "&yacute;")
sb.Replace(ChrW(&HFE), "&thorn;")
sb.Replace(ChrW(&HFF), "&yuml;")
sb.Replace(ChrW(&H152), "&OElig;")
sb.Replace(ChrW(&H153), "&oelig;")
sb.Replace(ChrW(&H160), "&Scaron;")
sb.Replace(ChrW(&H161), "&scaron;")
sb.Replace(ChrW(&H178), "&Yuml;")
sb.Replace(ChrW(&H192), "&fnof;")
sb.Replace(ChrW(&H2C6), "&circ;")
sb.Replace(ChrW(&H2DC), "&tilde;")
sb.Replace(ChrW(&H391), "&Alpha;")
sb.Replace(ChrW(&H392), "&Beta;")
sb.Replace(ChrW(&H393), "&Gamma;")
sb.Replace(ChrW(&H394), "&Delta;")
sb.Replace(ChrW(&H395), "&Epsilon;")
sb.Replace(ChrW(&H396), "&Zeta;")
sb.Replace(ChrW(&H397), "&Eta;")
sb.Replace(ChrW(&H398), "&Theta;")
sb.Replace(ChrW(&H399), "&Iota;")
sb.Replace(ChrW(&H39A), "&Kappa;")
sb.Replace(ChrW(&H39B), "&Lambda;")
sb.Replace(ChrW(&H39C), "&Mu;")
sb.Replace(ChrW(&H39D), "&Nu;")
sb.Replace(ChrW(&H39E), "&Xi;")
sb.Replace(ChrW(&H39F), "&Omicron;")
sb.Replace(ChrW(&H3A0), "&Pi;")
sb.Replace(ChrW(&H3A1), "&Rho;")
sb.Replace(ChrW(&H3A3), "&Sigma;")
sb.Replace(ChrW(&H3A4), "&Tau;")
sb.Replace(ChrW(&H3A5), "&Upsilon;")
sb.Replace(ChrW(&H3A6), "&Phi;")
sb.Replace(ChrW(&H3A7), "&Chi;")
sb.Replace(ChrW(&H3A8), "&Psi;")
sb.Replace(ChrW(&H3A9), "&Omega;")
sb.Replace(ChrW(&H3B1), "&alpha;")
sb.Replace(ChrW(&H3B2), "&beta;")
sb.Replace(ChrW(&H3B3), "&gamma;")
sb.Replace(ChrW(&H3B4), "&delta;")
sb.Replace(ChrW(&H3B5), "&epsilon;")
sb.Replace(ChrW(&H3B6), "&zeta;")
sb.Replace(ChrW(&H3B7), "&eta;")
sb.Replace(ChrW(&H3B8), "&theta;")
sb.Replace(ChrW(&H3B9), "&iota;")
sb.Replace(ChrW(&H3BA), "&kappa;")
sb.Replace(ChrW(&H3BB), "&lambda;")
sb.Replace(ChrW(&H3BC), "&mu;")
sb.Replace(ChrW(&H3BD), "&nu;")
sb.Replace(ChrW(&H3BE), "&xi;")
sb.Replace(ChrW(&H3BF), "&omicron;")
sb.Replace(ChrW(&H3C0), "&pi;")
sb.Replace(ChrW(&H3C1), "&rho;")
sb.Replace(ChrW(&H3C2), "&sigmaf;")
sb.Replace(ChrW(&H3C3), "&sigma;")
sb.Replace(ChrW(&H3C4), "&tau;")
sb.Replace(ChrW(&H3C5), "&upsilon;")
sb.Replace(ChrW(&H3C6), "&phi;")
sb.Replace(ChrW(&H3C7), "&chi;")
sb.Replace(ChrW(&H3C8), "&psi;")
sb.Replace(ChrW(&H3C9), "&omega;")
sb.Replace(ChrW(&H3D1), "&thetasym;")
sb.Replace(ChrW(&H3D2), "&upsih;")
sb.Replace(ChrW(&H3D6), "&piv;")
sb.Replace(ChrW(&H2002), "&ensp;")
sb.Replace(ChrW(&H2003), "&emsp;")
sb.Replace(ChrW(&H2009), "&thinsp;")
sb.Replace(ChrW(&H200C), "&zwnj;")
sb.Replace(ChrW(&H200D), "&zwj;")
sb.Replace(ChrW(&H200E), "&lrm;")
sb.Replace(ChrW(&H200F), "&rlm;")
sb.Replace(ChrW(&H2013), "&ndash;")
sb.Replace(ChrW(&H2014), "&mdash;")
sb.Replace(ChrW(&H2018), "&lsquo;")
sb.Replace(ChrW(&H2019), "&rsquo;")
sb.Replace(ChrW(&H201A), "&sbquo;")
sb.Replace(ChrW(&H201C), "&ldquo;")
sb.Replace(ChrW(&H201D), "&rdquo;")
sb.Replace(ChrW(&H201E), "&bdquo;")
sb.Replace(ChrW(&H2020), "&dagger;")
sb.Replace(ChrW(&H2021), "&Dagger;")
sb.Replace(ChrW(&H2022), "&bull;")
sb.Replace(ChrW(&H2026), "&hellip;")
sb.Replace(ChrW(&H2030), "&permil;")
sb.Replace(ChrW(&H2032), "&prime;")
sb.Replace(ChrW(&H2033), "&Prime;")
sb.Replace(ChrW(&H2039), "&lsaquo;")
sb.Replace(ChrW(&H203A), "&rsaquo;")
sb.Replace(ChrW(&H203E), "&oline;")
sb.Replace(ChrW(&H2044), "&frasl;")
sb.Replace(ChrW(&H20AC), "&euro;")
sb.Replace(ChrW(&H2111), "&image;")
sb.Replace(ChrW(&H2118), "&weierp;")
sb.Replace(ChrW(&H211C), "&real;")
sb.Replace(ChrW(&H2122), "&trade;")
sb.Replace(ChrW(&H2135), "&alefsym;")
sb.Replace(ChrW(&H2190), "&larr;")
sb.Replace(ChrW(&H2191), "&uarr;")
sb.Replace(ChrW(&H2192), "&rarr;")
sb.Replace(ChrW(&H2193), "&darr;")
sb.Replace(ChrW(&H2194), "&harr;")
sb.Replace(ChrW(&H21B5), "&crarr;")
sb.Replace(ChrW(&H21D0), "&lArr;")
sb.Replace(ChrW(&H21D1), "&uArr;")
sb.Replace(ChrW(&H21D2), "&rArr;")
sb.Replace(ChrW(&H21D3), "&dArr;")
sb.Replace(ChrW(&H21D4), "&hArr;")
sb.Replace(ChrW(&H2200), "&forall;")
sb.Replace(ChrW(&H2202), "&part;")
sb.Replace(ChrW(&H2203), "&exist;")
sb.Replace(ChrW(&H2205), "&empty;")
sb.Replace(ChrW(&H2207), "&nabla;")
sb.Replace(ChrW(&H2208), "&isin;")
sb.Replace(ChrW(&H2209), "&notin;")
sb.Replace(ChrW(&H220B), "&ni;")
sb.Replace(ChrW(&H220F), "&prod;")
sb.Replace(ChrW(&H2211), "&sum;")
sb.Replace(ChrW(&H2212), "&minus;")
sb.Replace(ChrW(&H2217), "&lowast;")
sb.Replace(ChrW(&H221A), "&radic;")
sb.Replace(ChrW(&H221D), "&prop;")
sb.Replace(ChrW(&H221E), "&infin;")
sb.Replace(ChrW(&H2220), "&ang;")
sb.Replace(ChrW(&H2227), "&and;")
sb.Replace(ChrW(&H2228), "&or;")
sb.Replace(ChrW(&H2229), "&cap;")
sb.Replace(ChrW(&H222A), "&cup;")
sb.Replace(ChrW(&H222B), "&int;")
sb.Replace(ChrW(&H2234), "&there4;")
sb.Replace(ChrW(&H223C), "&sim;")
sb.Replace(ChrW(&H2245), "&cong;")
sb.Replace(ChrW(&H2248), "&asymp;")
sb.Replace(ChrW(&H2260), "&ne;")
sb.Replace(ChrW(&H2261), "&equiv;")
sb.Replace(ChrW(&H2264), "&le;")
sb.Replace(ChrW(&H2265), "&ge;")
sb.Replace(ChrW(&H2282), "&sub;")
sb.Replace(ChrW(&H2283), "&sup;")
sb.Replace(ChrW(&H2284), "&nsub;")
sb.Replace(ChrW(&H2286), "&sube;")
sb.Replace(ChrW(&H2287), "&supe;")
sb.Replace(ChrW(&H2295), "&oplus;")
sb.Replace(ChrW(&H2297), "&otimes;")
sb.Replace(ChrW(&H22A5), "&perp;")
sb.Replace(ChrW(&H22C5), "&sdot;")
sb.Replace(ChrW(&H2308), "&lceil;")
sb.Replace(ChrW(&H2309), "&rceil;")
sb.Replace(ChrW(&H230A), "&lfloor;")
sb.Replace(ChrW(&H230B), "&rfloor;")
sb.Replace(ChrW(&H2329), "&lang;")
sb.Replace(ChrW(&H232A), "&rang;")
sb.Replace(ChrW(&H25CA), "&loz;")
sb.Replace(ChrW(&H2660), "&spades;")
sb.Replace(ChrW(&H2663), "&clubs;")
sb.Replace(ChrW(&H2665), "&hearts;")
sb.Replace(ChrW(&H2666), "&diams;")
sb.Replace(" ", " &nbsp;")
Return sb.ToString()
End Function
''' <summary>
''' Encodes the specified text as HTML.
''' </summary>
''' <param name="text">The text to be encoded.</param>
''' <returns>The encoded HTML.</returns>
<SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode", Justification:="This methos is simple a list of substuition character by its HTML representation.")> _
Public Function HtmlEncode(ByVal text As String) As String
Dim sb As New Text.StringBuilder(text)
sb.Replace(ChrW(&H26), "&amp;")
sb.Replace(ChrW(&H22), "&quot;")
sb.Replace(ChrW(&H27), "&apos;")
sb.Replace(ChrW(&H3C), "&lt;")
sb.Replace(ChrW(&H3E), "&gt;")
sb.Replace(ChrW(&HA0), "&nbsp;")
sb.Replace(ChrW(&HA1), "&iexcl;")
sb.Replace(ChrW(&HA2), "&cent;")
sb.Replace(ChrW(&HA3), "&pound;")
sb.Replace(ChrW(&HA4), "&curren;")
sb.Replace(ChrW(&HA5), "&yen;")
sb.Replace(ChrW(&HA6), "&brvbar;")
sb.Replace(ChrW(&HA7), "&sect;")
sb.Replace(ChrW(&HA8), "&uml;")
sb.Replace(ChrW(&HA9), "&copy;")
sb.Replace(ChrW(&HAA), "&ordf;")
sb.Replace(ChrW(&HAB), "&laquo;")
sb.Replace(ChrW(&HAC), "&not;")
sb.Replace(ChrW(&HAD), "&shy;")
sb.Replace(ChrW(&HAE), "&reg;")
sb.Replace(ChrW(&HAF), "&macr;")
sb.Replace(ChrW(&HB0), "&deg;")
sb.Replace(ChrW(&HB1), "&plusmn;")
sb.Replace(ChrW(&HB2), "&sup2;")
sb.Replace(ChrW(&HB3), "&sup3;")
sb.Replace(ChrW(&HB4), "&acute;")
sb.Replace(ChrW(&HB5), "&micro;")
sb.Replace(ChrW(&HB6), "&para;")
sb.Replace(ChrW(&HB7), "&middot;")
sb.Replace(ChrW(&HB8), "&cedil;")
sb.Replace(ChrW(&HB9), "&sup1;")
sb.Replace(ChrW(&HBA), "&ordm;")
sb.Replace(ChrW(&HBB), "&raquo;")
sb.Replace(ChrW(&HBC), "&frac14;")
sb.Replace(ChrW(&HBD), "&frac12;")
sb.Replace(ChrW(&HBE), "&frac34;")
sb.Replace(ChrW(&HBF), "&iquest;")
sb.Replace(ChrW(&HC0), "&Agrave;")
sb.Replace(ChrW(&HC1), "&Aacute;")
sb.Replace(ChrW(&HC2), "&Acirc;")
sb.Replace(ChrW(&HC3), "&Atilde;")
sb.Replace(ChrW(&HC4), "&Auml;")
sb.Replace(ChrW(&HC5), "&Aring;")
sb.Replace(ChrW(&HC6), "&AElig;")
sb.Replace(ChrW(&HC7), "&Ccedil;")
sb.Replace(ChrW(&HC8), "&Egrave;")
sb.Replace(ChrW(&HC9), "&Eacute;")
sb.Replace(ChrW(&HCA), "&Ecirc;")
sb.Replace(ChrW(&HCB), "&Euml;")
sb.Replace(ChrW(&HCC), "&Igrave;")
sb.Replace(ChrW(&HCD), "&Iacute;")
sb.Replace(ChrW(&HCE), "&Icirc;")
sb.Replace(ChrW(&HCF), "&Iuml;")
sb.Replace(ChrW(&HD0), "&ETH;")
sb.Replace(ChrW(&HD1), "&Ntilde;")
sb.Replace(ChrW(&HD2), "&Ograve;")
sb.Replace(ChrW(&HD3), "&Oacute;")
sb.Replace(ChrW(&HD4), "&Ocirc;")
sb.Replace(ChrW(&HD5), "&Otilde;")
sb.Replace(ChrW(&HD6), "&Ouml;")
sb.Replace(ChrW(&HD7), "&times;")
sb.Replace(ChrW(&HD8), "&Oslash;")
sb.Replace(ChrW(&HD9), "&Ugrave;")
sb.Replace(ChrW(&HDA), "&Uacute;")
sb.Replace(ChrW(&HDB), "&Ucirc;")
sb.Replace(ChrW(&HDC), "&Uuml;")
sb.Replace(ChrW(&HDD), "&Yacute;")
sb.Replace(ChrW(&HDE), "&THORN;")
sb.Replace(ChrW(&HDF), "&szlig;")
sb.Replace(ChrW(&HE0), "&agrave;")
sb.Replace(ChrW(&HE1), "&aacute;")
sb.Replace(ChrW(&HE2), "&acirc;")
sb.Replace(ChrW(&HE3), "&atilde;")
sb.Replace(ChrW(&HE4), "&auml;")
sb.Replace(ChrW(&HE5), "&aring;")
sb.Replace(ChrW(&HE6), "&aelig;")
sb.Replace(ChrW(&HE7), "&ccedil;")
sb.Replace(ChrW(&HE8), "&egrave;")
sb.Replace(ChrW(&HE9), "&eacute;")
sb.Replace(ChrW(&HEA), "&ecirc;")
sb.Replace(ChrW(&HEB), "&euml;")
sb.Replace(ChrW(&HEC), "&igrave;")
sb.Replace(ChrW(&HED), "&iacute;")
sb.Replace(ChrW(&HEE), "&icirc;")
sb.Replace(ChrW(&HEF), "&iuml;")
sb.Replace(ChrW(&HF0), "&eth;")
sb.Replace(ChrW(&HF1), "&ntilde;")
sb.Replace(ChrW(&HF2), "&ograve;")
sb.Replace(ChrW(&HF3), "&oacute;")
sb.Replace(ChrW(&HF4), "&ocirc;")
sb.Replace(ChrW(&HF5), "&otilde;")
sb.Replace(ChrW(&HF6), "&ouml;")
sb.Replace(ChrW(&HF7), "&divide;")
sb.Replace(ChrW(&HF8), "&oslash;")
sb.Replace(ChrW(&HF9), "&ugrave;")
sb.Replace(ChrW(&HFA), "&uacute;")
sb.Replace(ChrW(&HFB), "&ucirc;")
sb.Replace(ChrW(&HFC), "&uuml;")
sb.Replace(ChrW(&HFD), "&yacute;")
sb.Replace(ChrW(&HFE), "&thorn;")
sb.Replace(ChrW(&HFF), "&yuml;")
sb.Replace(ChrW(&H152), "&OElig;")
sb.Replace(ChrW(&H153), "&oelig;")
sb.Replace(ChrW(&H160), "&Scaron;")
sb.Replace(ChrW(&H161), "&scaron;")
sb.Replace(ChrW(&H178), "&Yuml;")
sb.Replace(ChrW(&H192), "&fnof;")
sb.Replace(ChrW(&H2C6), "&circ;")
sb.Replace(ChrW(&H2DC), "&tilde;")
sb.Replace(ChrW(&H391), "&Alpha;")
sb.Replace(ChrW(&H392), "&Beta;")
sb.Replace(ChrW(&H393), "&Gamma;")
sb.Replace(ChrW(&H394), "&Delta;")
sb.Replace(ChrW(&H395), "&Epsilon;")
sb.Replace(ChrW(&H396), "&Zeta;")
sb.Replace(ChrW(&H397), "&Eta;")
sb.Replace(ChrW(&H398), "&Theta;")
sb.Replace(ChrW(&H399), "&Iota;")
sb.Replace(ChrW(&H39A), "&Kappa;")
sb.Replace(ChrW(&H39B), "&Lambda;")
sb.Replace(ChrW(&H39C), "&Mu;")
sb.Replace(ChrW(&H39D), "&Nu;")
sb.Replace(ChrW(&H39E), "&Xi;")
sb.Replace(ChrW(&H39F), "&Omicron;")
sb.Replace(ChrW(&H3A0), "&Pi;")
sb.Replace(ChrW(&H3A1), "&Rho;")
sb.Replace(ChrW(&H3A3), "&Sigma;")
sb.Replace(ChrW(&H3A4), "&Tau;")
sb.Replace(ChrW(&H3A5), "&Upsilon;")
sb.Replace(ChrW(&H3A6), "&Phi;")
sb.Replace(ChrW(&H3A7), "&Chi;")
sb.Replace(ChrW(&H3A8), "&Psi;")
sb.Replace(ChrW(&H3A9), "&Omega;")
sb.Replace(ChrW(&H3B1), "&alpha;")
sb.Replace(ChrW(&H3B2), "&beta;")
sb.Replace(ChrW(&H3B3), "&gamma;")
sb.Replace(ChrW(&H3B4), "&delta;")
sb.Replace(ChrW(&H3B5), "&epsilon;")
sb.Replace(ChrW(&H3B6), "&zeta;")
sb.Replace(ChrW(&H3B7), "&eta;")
sb.Replace(ChrW(&H3B8), "&theta;")
sb.Replace(ChrW(&H3B9), "&iota;")
sb.Replace(ChrW(&H3BA), "&kappa;")
sb.Replace(ChrW(&H3BB), "&lambda;")
sb.Replace(ChrW(&H3BC), "&mu;")
sb.Replace(ChrW(&H3BD), "&nu;")
sb.Replace(ChrW(&H3BE), "&xi;")
sb.Replace(ChrW(&H3BF), "&omicron;")
sb.Replace(ChrW(&H3C0), "&pi;")
sb.Replace(ChrW(&H3C1), "&rho;")
sb.Replace(ChrW(&H3C2), "&sigmaf;")
sb.Replace(ChrW(&H3C3), "&sigma;")
sb.Replace(ChrW(&H3C4), "&tau;")
sb.Replace(ChrW(&H3C5), "&upsilon;")
sb.Replace(ChrW(&H3C6), "&phi;")
sb.Replace(ChrW(&H3C7), "&chi;")
sb.Replace(ChrW(&H3C8), "&psi;")
sb.Replace(ChrW(&H3C9), "&omega;")
sb.Replace(ChrW(&H3D1), "&thetasym;")
sb.Replace(ChrW(&H3D2), "&upsih;")
sb.Replace(ChrW(&H3D6), "&piv;")
sb.Replace(ChrW(&H2002), "&ensp;")
sb.Replace(ChrW(&H2003), "&emsp;")
sb.Replace(ChrW(&H2009), "&thinsp;")
sb.Replace(ChrW(&H200C), "&zwnj;")
sb.Replace(ChrW(&H200D), "&zwj;")
sb.Replace(ChrW(&H200E), "&lrm;")
sb.Replace(ChrW(&H200F), "&rlm;")
sb.Replace(ChrW(&H2013), "&ndash;")
sb.Replace(ChrW(&H2014), "&mdash;")
sb.Replace(ChrW(&H2018), "&lsquo;")
sb.Replace(ChrW(&H2019), "&rsquo;")
sb.Replace(ChrW(&H201A), "&sbquo;")
sb.Replace(ChrW(&H201C), "&ldquo;")
sb.Replace(ChrW(&H201D), "&rdquo;")
sb.Replace(ChrW(&H201E), "&bdquo;")
sb.Replace(ChrW(&H2020), "&dagger;")
sb.Replace(ChrW(&H2021), "&Dagger;")
sb.Replace(ChrW(&H2022), "&bull;")
sb.Replace(ChrW(&H2026), "&hellip;")
sb.Replace(ChrW(&H2030), "&permil;")
sb.Replace(ChrW(&H2032), "&prime;")
sb.Replace(ChrW(&H2033), "&Prime;")
sb.Replace(ChrW(&H2039), "&lsaquo;")
sb.Replace(ChrW(&H203A), "&rsaquo;")
sb.Replace(ChrW(&H203E), "&oline;")
sb.Replace(ChrW(&H2044), "&frasl;")
sb.Replace(ChrW(&H20AC), "&euro;")
sb.Replace(ChrW(&H2111), "&image;")
sb.Replace(ChrW(&H2118), "&weierp;")
sb.Replace(ChrW(&H211C), "&real;")
sb.Replace(ChrW(&H2122), "&trade;")
sb.Replace(ChrW(&H2135), "&alefsym;")
sb.Replace(ChrW(&H2190), "&larr;")
sb.Replace(ChrW(&H2191), "&uarr;")
sb.Replace(ChrW(&H2192), "&rarr;")
sb.Replace(ChrW(&H2193), "&darr;")
sb.Replace(ChrW(&H2194), "&harr;")
sb.Replace(ChrW(&H21B5), "&crarr;")
sb.Replace(ChrW(&H21D0), "&lArr;")
sb.Replace(ChrW(&H21D1), "&uArr;")
sb.Replace(ChrW(&H21D2), "&rArr;")
sb.Replace(ChrW(&H21D3), "&dArr;")
sb.Replace(ChrW(&H21D4), "&hArr;")
sb.Replace(ChrW(&H2200), "&forall;")
sb.Replace(ChrW(&H2202), "&part;")
sb.Replace(ChrW(&H2203), "&exist;")
sb.Replace(ChrW(&H2205), "&empty;")
sb.Replace(ChrW(&H2207), "&nabla;")
sb.Replace(ChrW(&H2208), "&isin;")
sb.Replace(ChrW(&H2209), "&notin;")
sb.Replace(ChrW(&H220B), "&ni;")
sb.Replace(ChrW(&H220F), "&prod;")
sb.Replace(ChrW(&H2211), "&sum;")
sb.Replace(ChrW(&H2212), "&minus;")
sb.Replace(ChrW(&H2217), "&lowast;")
sb.Replace(ChrW(&H221A), "&radic;")
sb.Replace(ChrW(&H221D), "&prop;")
sb.Replace(ChrW(&H221E), "&infin;")
sb.Replace(ChrW(&H2220), "&ang;")
sb.Replace(ChrW(&H2227), "&and;")
sb.Replace(ChrW(&H2228), "&or;")
sb.Replace(ChrW(&H2229), "&cap;")
sb.Replace(ChrW(&H222A), "&cup;")
sb.Replace(ChrW(&H222B), "&int;")
sb.Replace(ChrW(&H2234), "&there4;")
sb.Replace(ChrW(&H223C), "&sim;")
sb.Replace(ChrW(&H2245), "&cong;")
sb.Replace(ChrW(&H2248), "&asymp;")
sb.Replace(ChrW(&H2260), "&ne;")
sb.Replace(ChrW(&H2261), "&equiv;")
sb.Replace(ChrW(&H2264), "&le;")
sb.Replace(ChrW(&H2265), "&ge;")
sb.Replace(ChrW(&H2282), "&sub;")
sb.Replace(ChrW(&H2283), "&sup;")
sb.Replace(ChrW(&H2284), "&nsub;")
sb.Replace(ChrW(&H2286), "&sube;")
sb.Replace(ChrW(&H2287), "&supe;")
sb.Replace(ChrW(&H2295), "&oplus;")
sb.Replace(ChrW(&H2297), "&otimes;")
sb.Replace(ChrW(&H22A5), "&perp;")
sb.Replace(ChrW(&H22C5), "&sdot;")
sb.Replace(ChrW(&H2308), "&lceil;")
sb.Replace(ChrW(&H2309), "&rceil;")
sb.Replace(ChrW(&H230A), "&lfloor;")
sb.Replace(ChrW(&H230B), "&rfloor;")
sb.Replace(ChrW(&H2329), "&lang;")
sb.Replace(ChrW(&H232A), "&rang;")
sb.Replace(ChrW(&H25CA), "&loz;")
sb.Replace(ChrW(&H2660), "&spades;")
sb.Replace(ChrW(&H2663), "&clubs;")
sb.Replace(ChrW(&H2665), "&hearts;")
sb.Replace(ChrW(&H2666), "&diams;")
sb.Replace(" ", " &nbsp;")
Return sb.ToString()
End Function
Sub AddTokenizerBaseMacros(ByVal tokenizer As Tokenization.Tokenizer)
Sub AddTokenizerBaseMacros(ByVal tokenizer As Tokenization.Tokenizer)
'*
'* Prepares the BBCode Grammar
'*
With tokenizer
.Options = RegexOptions.Singleline Or RegexOptions.IgnoreCase
'*
'* Prepares the BBCode Grammar
'*
With tokenizer
.Options = RegexOptions.Singleline Or RegexOptions.IgnoreCase
'*
'* Define the grammar macros
'*
.AddMacro("h", "[0-9a-f]")
.AddMacro("nl", "\n|\r\n|\r|\f")
.AddMacro("space", "[ \t\r\n\f]+")
.AddMacro("s", "[ \t\r\n\f]*")
.AddMacro("w", "{s}?")
.AddMacro("nonascii", "[\u0080-\uffff]")
.AddMacro("unicode", "\\{h}{1,6}(\r\n|[ \t\r\n\f])?")
.AddMacro("escape", "{unicode}|\\[^\r\n\f0-9a-f]")
.AddMacro("nmstart", "[_a-z]|{nonascii}|{escape}")
.AddMacro("nmchar", "[_a-z0-9-]|{nonascii}|{escape}")
.AddMacro("string1", "\""([^\n\r\f\\""]|\\{nl}|{escape})*\""")
.AddMacro("string2", "\'([^\n\r\f\\']|\\{nl}|{escape})*\'")
.AddMacro("invalid1", "\""([^\n\r\f\\""]|\\{nl}|{escape})*")
.AddMacro("invalid2", "\'([^\n\r\f\\']|\\{nl}|{escape})*")
.AddMacro("name", "{nmchar}+")
.AddMacro("num", "[0-9]+|[0-9]*\.[0-9]+")
.AddMacro("string", "{string1}|{string2}")
.AddMacro("invalid", "{invalid1}|{invalid2}")
.AddMacro("url", "(ftp|https?://)" & _
"(([0-9a-z_!~*'().&=+$%-]+):([0-9a-z_!~*'().&=+$%-]+@))?" & _
"(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})" & _
"(:[0-9]{1,4})?" & _
"((/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?|(/?))")
.AddMacro("mail", "(?:mailto:)?[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}")
.AddMacro("value", "{string}|{mail}|{url}|{num}|{name}")
.AddMacro("param", "{name}{w}={w}{value}")
.AddMacro("params", "({space}({param}|{name}))+")
'*
'* Define the grammar macros
'*
.AddMacro("h", "[0-9a-f]")
.AddMacro("nl", "\n|\r\n|\r|\f")
.AddMacro("space", "[ \t\r\n\f]+")
.AddMacro("s", "[ \t\r\n\f]*")
.AddMacro("w", "{s}?")
.AddMacro("nonascii", "[\u0080-\uffff]")
.AddMacro("unicode", "\\{h}{1,6}(\r\n|[ \t\r\n\f])?")
.AddMacro("escape", "{unicode}|\\[^\r\n\f0-9a-f]")
.AddMacro("nmstart", "[_a-z]|{nonascii}|{escape}")
.AddMacro("nmchar", "[_a-z0-9-]|{nonascii}|{escape}")
.AddMacro("string1", "\""([^\n\r\f\\""]|\\{nl}|{escape})*\""")
.AddMacro("string2", "\'([^\n\r\f\\']|\\{nl}|{escape})*\'")
.AddMacro("invalid1", "\""([^\n\r\f\\""]|\\{nl}|{escape})*")
.AddMacro("invalid2", "\'([^\n\r\f\\']|\\{nl}|{escape})*")
.AddMacro("name", "{nmchar}+")
.AddMacro("num", "[0-9]+|[0-9]*\.[0-9]+")
.AddMacro("string", "{string1}|{string2}")
.AddMacro("invalid", "{invalid1}|{invalid2}")
.AddMacro("url", "(ftp|https?://)" & _
"(([0-9a-z_!~*'().&=+$%-]+):([0-9a-z_!~*'().&=+$%-]+@))?" & _
"(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})" & _
"(:[0-9]{1,4})?" & _
"((/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?|(/?))")
.AddMacro("mail", "(?:mailto:)?[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}")
.AddMacro("value", "{string}|{mail}|{url}|{num}|{name}")
.AddMacro("param", "{name}{w}={w}{value}")
.AddMacro("params", "({space}({param}|{name}))+")
End With
End Sub
End With
End Sub
End Module

Loading…
Cancel
Save