[Solved] SyntaxHighlighter issues after upgrading BlogEngine.NET from 2.6 to 2.7

Problem:

I updated my BlogEngine.NET from 2.6 to 2.7, and everything goes well. But one day I found that the syntax highlighter were functioning horribly poor. They are:

  1. Js error thrown on every post page claming:
    Uncaught ReferenceError: SyntaxHighlighter is not defined
  2. Tabs were removed inside code block.
  3. Auto text wrap not work at the long text lines.

Cause:

  1. The js error only happens if you turned on SyntaxHighlighter extension, and checked “collapse” option.
    [Solved] SyntaxHighlighter issues after upgrading BlogEngine.NET from 2.6 to 2.7
    It will add a script line after the syntax highlighter js files were referenced like this:
    1
    2
    3
    4
    5
    6
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shCore.js" defer="defer" async="async"></script>
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shAutoloader.js" defer="defer" async="async"></script>
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shInit.js" defer="defer" async="async"></script><script type="text/javascript" defer="defer">
        SyntaxHighlighter.defaults['collapse'] = true;
    });
    </script>
    I guess the defer=”defer” async=”async” attributes makes the execution order is unpredictable, so the last line `SyntaxHighlighter.defaults[‘collapse’] = true` actually executes before the shCore.js loaded.
  2. This is because in the site.master.cs, there is a line of code:
    1
    html = reg.Replace(html, string.Empty).Trim();
  3. As be explained in this article, it is caused by the Syntax Highlighter 3.x separated the gutter and code so that when you copy code you won’t copy the line numbers. This is a good thing, but it forgot or gave up the auto line wrap functionality because it was hard to keep it.

Solution:

  1. Improve the SyntaxHighlighter extension so that it generates script codes like this to make sure when setting the SyntaxHighlighter.defaults, the SyntaxHighlighter had already been defined.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shCore.js" defer="defer" async="async"></script>
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shAutoloader.js" defer="defer" async="async"></script>
    <script type="text/javascript" src="/Scripts/syntaxhighlighter/shInit.js" defer="defer" async="async"></script><script type="text/javascript" defer="defer">
     
            if (typeof executeOn === 'undefined') {
                window.executeOn = function (condition, func) {
                    var interval = setInterval(function () {
                        try {
                            var result = false;
     
                            if (typeof condition === "function") {
                                result = condition();
                            } else if (typeof condition === "string") {
                                result = eval(condition);
                            } else {
                                throw "argument 'condition' must be a bool function or a bool expression.";
                            }
     
                            if (result === true) {
                                clearInterval(interval);
                                func();
                            }
                        } catch (ex) {
                            clearInterval(interval);
                            throw ex;
                        }
                    }, 100);
                };
            }
     
        // Make sure the SyntaxHighlighter has already been defined, otherwise wait a chunk of time
        executeOn("typeof SyntaxHighlighter !== 'undefined' ", function() {
            SyntaxHighlighter.defaults['collapse'] = true;
     
            executeOn("document.readyState === 'loaded' || document.readyState === 'complete'", function() {
                SyntaxHighlighter.all();
                    });
        });
    </script>
    The updated SyntaxHighlighter extension(SyntaxHighlighter.cs, if you don't have it, add it to the ~/App_Code/ folder in your BlogEngine.NET project) looks like this:
  2. Open your site.master.cs, and comment out the line as below shows inside the Render method.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    protected override void Render(HtmlTextWriter writer)
        {
            using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new System.IO.StringWriter()))
            {
                base.Render(htmlwriter);
                string html = htmlwriter.InnerWriter.ToString();
     
                //html = reg.Replace(html, string.Empty).Trim();
     
                writer.Write(html);
            }
        }
  3. Go to your BlogEngine.NET Control panel, navigate to “Settings/Custom code” pane, and paste the following code to the “head section”:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <style type="text/css">
        body .syntaxhighlighter .line {
            white-space: pre-wrap !important;
        }
    </style>
     
    <script type="text/javascript" id="line-word-wrap-syntax-highlighter">
        $(function () {
            // Line wrap back
            var shLineWrap = function () {
                // Fix by Jeff Tian that make it work with the collapsed setting
                $('.syntaxhighlighter:not(.collapsed)').each(function () {
                    // Fetch
                    var $sh = $(this),
                        $gutter = $sh.find('td.gutter'),
                        $code = $sh.find('td.code')
                    ;
                    // Cycle through lines
                    $gutter.children('.line').each(function (i) {
                        // Fetch
                        var $gutterLine = $(this),
                            $codeLine = $code.find('.line:nth-child(' + (i + 1) + ')')
                        ;
                        //alert($gutterLine);
                        // Fetch height
                        var height = $codeLine.height() || 0;
                        if (!height) {
                            height = 'auto';
                        }
                        else {
                            height = height += 'px';
                            //alert(height);
                        }
                        // Copy height over
                        $gutterLine.attr('style', 'height: ' + height + ' !important'); // fix by Edi, for JQuery 1.7+ under Firefox 15.0
                    });
                });
            };
     
            // Line wrap back when syntax highlighter has done it's stuff
            var shLineWrapWhenReady = function () {
                if ($('.syntaxhighlighter').length === 0) {
                    setTimeout(shLineWrapWhenReady, 100);
                }
                else {
                    shLineWrap();
                    // Fix by Jeff Tian that make it work with the collapsed setting
                    if ($(".syntaxhighlighter.collapsed").length > 0) {
                        setTimeout(shLineWrapWhenReady, 100);
                    }
                }
            };
     
            // Fire
            shLineWrapWhenReady();
        });
    </script>
    Screenshot:
    [Solved] SyntaxHighlighter issues after upgrading BlogEngine.NET from 2.6 to 2.7
  4. Now all issues related to SyntaxHighlighter are resolved!

Add comment

Loading