The last part of my HTML genrator requries a few styles. Because all styles are inline and the styling is for emails there won't be any fancy selectors, just by element, id or class.
The most complex css might look like this:
var css = @"
h1 {
font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
}
h2 {
font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
}
#foo, p {
font-family: Sans-Serif; color: green;
}
hr, .foo {
border: 0; border-bottom: 1px solid #ccc; background: #ccc;
}";
I read it into a dictionary that the StyleVisitor
will consume and applay.
static class Css
{
public static IDictionary<string, string> Parse(string css)
{
return
Regex
// Match "selector { declarations }"
.Matches(css.Minify(), @"(?<selectors>[a-z0-9_\-\.,\s#]+)\s*{(?<declarations>.+?)}", RegexOptions.IgnoreCase)
.Cast<Match>()
.Select(m => Regex
// Split selectors separated by ",".
.Split(m.Groups["selectors"].Value, @",")
// Skip empty results.
.Where(s => !string.IsNullOrEmpty(s))
.Select(selector => new KeyValuePair<string, string>(
key: selector.Trim().ToLowerInvariant(),
value: m.Groups["declarations"].Value.Trim())))
.SelectMany(x => x)
.ToDictionary(x => x.Key, x => x.Value);
}
private static string Minify(this string css) => Regex.Replace(css, @"(\r\n|\r|\n)", string.Empty);
}
I'm assuming the css does not require any vaidation because it's been created and validated with an editor like jsfiddle etc.
The result of Css.Parse(css)
is
h1 font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
h2 font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
#foo font-family: Sans-Serif; color: green;
p font-family: Sans-Serif; color: green;
hr border: 0; border-bottom: 1px solid #ccc; background: #ccc
.foo border: 0; border-bottom: 1px solid #ccc; background: #ccc