PoLaKoSz / CodeKicker.BBCode

Fully documented and Unit tested .NET Standard 2.0 BBCode to HTML parser.
http://bbcode.codeplex.com/
MIT License
2 stars 0 forks source link

BBCode Validation #1

Open BenjaminAbt opened 4 years ago

BenjaminAbt commented 4 years ago

Hi, is it possible to validate attributes?

For example: you show a font-sample with font-size 12px.

Sample:

I know I can pass contentTransformers, but the usage is not clear and the original CodeKicker docs are down :-/

PoLaKoSz commented 4 years ago

Hi!

Thank You for checking out this repository! :)

How to validate attribute value

Maybe this is not the most elegant way, but here is a solution:

var bbTags = new List<BBTag>()
{
    new BBTag("font", "<div style=\"font-size: ${fontSize}\">", "</div>",
        new BBAttribute(
            "fontSize",
            "size",
            ((attr) =>
            {
                try
                {
                    int size = Convert.ToInt32(attr.AttributeValue);
                    return $"{attr.AttributeValue}px";
                }
                catch (FormatException ex)
                {
                    throw new FormatException($"Font size is not a whole number, but {attr.AttributeValue}", ex);
                }
            })))
};

var parser = new BBCodeParser(bbTags);

string output = parser.ToHtml("[font size=car]Lorem ipsum[/font]");

Enrich the value

var bbTags = new List<BBTag>()
{
    new BBTag("font", "<div style=\"font-size: ${fontSize}\">", "</div>",
        new BBAttribute("fontSize", "size", fontSize => $"{fontSize.AttributeValue}px"))
};

var parser = new BBCodeParser(bbTags);

string output = parser.ToHtml("[font size=12]Lorem ipsum[/font]");

Last two sample

I am not sure about what to comment on the last two because this library just do BBCode to HTML parsing and cannot do (yet) HTML to BBCode so i don't understand how [font]Lorem ipsum[/font] should be [font]Lorem ipsum[/font]. Can You provide more details on this?

BenjaminAbt commented 4 years ago

Thank you for the very fast answer. Awesome!

So the contentTransformers is the right place. Thanks. The enrich syntax is a nice solution!

The last two samples are pretty simple; the idea is the validation result handling. I'd like to avoid exceptions to avoid hard error handling, would like to use a "soft'ish error handling":

PoLaKoSz commented 4 years ago

Cannot test this, but should work

Return fixed value

var bbTags = new List<BBTag>()
{
    new BBTag("font", "<div style=\"font-size: ${fontSize}\">", "</div>",
        new BBAttribute(
            "fontSize",
            "size",
            ((attr) =>
            {
                try
                {
                    int size = Convert.ToInt32(attr.AttributeValue);

                    if (size < 10)
                        return "10";
                    else if (16 < size)
                        return "16";
                    else
                        return $"{size}";
                }
                catch (FormatException ex)
                {
                    throw new FormatException($"Font size is not a whole number, but {attr.AttributeValue}", ex);
                }
            })))
};

var parser = new BBCodeParser(bbTags);

string output1 = parser.ToHtml("[font size=8]Lorem ipsum[/font]");
string output2 = parser.ToHtml("[font size=12]Lorem ipsum[/font]");
string output3 = parser.ToHtml("[font size=18]Lorem ipsum[/font]");

Return plain input if invalid

This could be done with a little changes in the Return fixed value block:

return $"{attr.Attribute.ID}: {attr.AttributeValue}";
BenjaminAbt commented 4 years ago

Thanks for your help.

I dipped into the source code step by step, and my scenario is currently not supported in the original code.

With a FormatException an exception is thrown despite ErrorFree-Mode, which was probably the sense at that time, but doesn't fit for me.

I have now made the following change, which results in the input being returned unchanged for a format exception.

        new BBTag("size", "<span style=\"font-size: ${size}\">" ,"</span>",
                new BBAttribute("size", "", BBCodeResolvers.GetSizeValue)),
        public static string GetSizeValue(IAttributeRenderingContext attributeRenderingContext)
        {
            string size = attributeRenderingContext.GetAttributeValueById("size");

            if (!int.TryParse(size, out int sizeVal)) throw new FormatException();
            return Math.Max(10, Math.Min(16, sizeVal)).ToString();
        }
// BBCodeParser.cs
        public virtual string ToHtml(string bbCode)
        {
            if (bbCode == null) throw new ArgumentNullException(nameof(bbCode));
            SequenceNode node = ParseSyntaxTree(bbCode);
            try
            {
                return node.ToHtml();
            }
            catch (FormatException)
            {
                if (ErrorMode == ErrorMode.ErrorFree)
                {
                    return bbCode;
                }

                throw;
            }
        }
BenjaminAbt commented 4 years ago

Found a better solution, just override TagNode.cs

        public override string ToHtml()
        {
            try
            {
                string content = GetContent();

                string start = ReplaceAttributeValues(Tag.OpenTagTemplate, content);
                string body = (Tag.AutoRenderContent ? content : null);
                string end = ReplaceAttributeValues(Tag.CloseTagTemplate, content);

                string transformedContent = start + body + end;

                return transformedContent;
            }
            catch (FormatException)
            {
                return ToBBCode();
            }
        }

Results is: only the invalid bbcode is returned raw, not the whole input.