Skip to content

HTML with CSS or JavaScript

axunonb edited this page Mar 4, 2022 · 5 revisions

What is the issue?

A frequent question being asked is: We get errors when using SmartFormat with a format string that contains HTML with CSS and/or JavaScript included.

While processing pure HTML works absolutely fine, the result becomes unpredictable with CSS and/or JavaScript.

The reason is obvious: SmartFormat uses braces to identify Placeholders, which are at the same time part of the CSS/JavaScript notation.

Solutions

1. Modify SmartSettings

In v2, you could get the desired results, when setting Settings.ParseErrorAction = ErrorAction.MaintainTokens. This may still help with v3.

New in v3:

We introduced an experimental bool ParserSettings.ParseInputAsHtml. The default is false.

If true, theParser will parse all content inside <script> and <style> tags as LiteralText. All other places may still contain Placeholders.

This is because <script> and <style> tags may contain curly or square braces, that interfere with the SmartFormat {Placeholder}.

Best results can only be expected with clean HTML: balanced opening and closing tags, single and double quotes. Also, do not use angle brackets, single and double quotes in script or style comments.

2. Pre-Process HTML with an HTML Parser

SmartFormat is not a fully-fledged HTML parser. If this is required, use AngleSharp or HtmlAgilityPack.

Therefore, it is strongly recommended to pre-process HTML with CSS/JavaScript using the AngleSharp library. The following sample shows that only three extra lines of code will help.

Note: The example assumes, that CSS/JavaScript is located outside the <body>tag.

using AngleSharp;

Here is the HTML part:

var html = @"
<html>
    <head>
        <script>
            (function() {
                var ep;
                var loginState;
                try {
                    window.localStorage && (ep = JSON.parse(window.localStorage.getItem('dl_ep') || 'false'));
                window.localStorage && (loginState = JSON.parse(window.localStorage.getItem('dl_loginState')) || undefined);
            } catch(e) {
                console.error(e);
            }
        </script>
        <style type='text/css'>
            .site-sticky-top {
                position: -webkit-sticky;
                position: sticky;
                top: 0;
                z-index: 1020;
            }
        </style>
    </head>
    <body>
        <div class='main'>
            My name is {Name}. I'm living in {City}.
        </div>
    </body>
</html>
";

Here's the code for parsing HTML with AngleSharp and formatting with SmartFormat:

var variables = new { Name = "John Long", City = "New York" };

// Create a new parser front-end (can be re-used)
var parser = new AngleSharp.Html.Parser.HtmlParser();

// Get the DOM representation
AngleSharp.Html.Dom.IHtmlDocument htmlDocument = parser.ParseDocument(html);

// ##### Smart.Format the HTML body: #####
htmlDocument.Body.InnerHtml = Smart.Format(htmlDocument.Body.InnerHtml, variables);

// This gets the complete HTML as a string
var result = htmlDocument.ToHtml();
Clone this wiki locally