HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Css builder and parser

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
andparsercssbuilder

Problem

As part of a larger project I've created recently a simple CssBuilder and CssParser. It's composed of three classes and can parse/build inline and block CSS. Its main purpose was to render CSS for inline styles for email formatting (which is the rest of the project (maybe another time)). I also tried to design a fluent API here.

CssBuilder

public class CssBuilder
{
    public string Selector { get; set; }

    public IList Declarations { get; internal set; } = new List();

    public static CssBuilder Create()
    {
        return new CssBuilder();
    }

    public static CssBuilder CreateFor(string selectror)
    {
        return new CssBuilder { Selector = selectror };
    }

    public static CssBuilder CreateFrom(string css)
    {
        return CssParser.ParseCss(css);
    }

    public CssBuilder Declare(string property, string value)
    {
        Declarations.Add(new CssDeclaration
        {
            Property = property,
            Value = value.TrimEnd(';')
        });
        return this;
    }

    public string BuildCss()
    {
        return string.IsNullOrEmpty(Selector) ? BuildInlineCss(this) : BuildBlockCss(this);
    }

    internal string BuildInlineCss(CssBuilder builder)
    {
        return builder.Declarations.Aggregate(string.Empty, (current, next) => string.IsNullOrEmpty(current) ? next.ToString() : $"{current} {next}");
    }

    internal string BuildBlockCss(CssBuilder builder)
    {
        const int indentWidth = 3;

        var block = new StringBuilder();
        block.Append(builder.Selector);
        block.AppendLine(" {");
        foreach (var declaration in builder.Declarations)
        {
            block.Append(string.Empty.PadLeft(indentWidth));
            block.AppendLine(declaration.ToString());
        }
        block.Append("}");

        return block.ToString();
    }
}


CssParser

```
public class CssParser
{
public static CssBuilder ParseCss(string css)
{
var builder = new CssBuilde

Solution

CssBuilder

internal string BuildBlockCss(CssBuilder builder)
{
    const int indentWidth = 3;

    var block = new StringBuilder();
    block.Append(builder.Selector);
    block.AppendLine(" {");
    foreach (var declaration in builder.Declarations)
    {
        block.Append(string.Empty.PadLeft(indentWidth));
        block.AppendLine(declaration.ToString());
    }
    block.Append("}");

    return block.ToString();
}


Instead of having a const int indentWidth I would prefer to have either a const string of just string. In this way you wouldn't need to call string.Empty.PadLeft(indentWidth) for each iteration of the loop.

Starting the "Data section" with block.AppendLine(" {"); and ending it with block.Append("}"); (missing leading space) will look odd in the css block.

The StringBuilder's methods are implemented fluently so you could use the returned instance of the StringBuilder.

Using the overloaded constructor of the StringBuilder which takes a capacity as an argument is better if you know that the content of the StringBuilder will exceed 16 characters, because if this initial capacity is reached the current capacity is doubled.

internal string BuildBlockCss(CssBuilder builder)
{
    const int indentWidth = 3;
    string indentValue = string.Empty.PadLeft(indentWidth);

    var block = new StringBuilder(1024);
    block.Append(builder.Selector)
         .AppendLine(" {")

    foreach (var declaration in builder.Declarations)
    {
        block.Append(indentValue)
             .AppendLine(declaration.ToString());
    }

    block.Append("}");

    return block.ToString();
}


you should also think about wether it would be good to have an optional parameter defining the indentWidth instead of hardcoding it.

Code Snippets

internal string BuildBlockCss(CssBuilder builder)
{
    const int indentWidth = 3;

    var block = new StringBuilder();
    block.Append(builder.Selector);
    block.AppendLine(" {");
    foreach (var declaration in builder.Declarations)
    {
        block.Append(string.Empty.PadLeft(indentWidth));
        block.AppendLine(declaration.ToString());
    }
    block.Append("}");

    return block.ToString();
}
internal string BuildBlockCss(CssBuilder builder)
{
    const int indentWidth = 3;
    string indentValue = string.Empty.PadLeft(indentWidth);

    var block = new StringBuilder(1024);
    block.Append(builder.Selector)
         .AppendLine(" {")

    foreach (var declaration in builder.Declarations)
    {
        block.Append(indentValue)
             .AppendLine(declaration.ToString());
    }

    block.Append("}");

    return block.ToString();
}

Context

StackExchange Code Review Q#109383, answer score: 2

Revisions (0)

No revisions yet.