长代码换行是SyntaxHighlighter3.0版本之前的功能,但3.0之后就木了,本人认为主要猿因是gutter(代码行号指示器)的换行难做。因为3.x版是将代码行号和代码部分分开生成HTML的,猿来的老版本是在一起的。这样做是便于直接复制代码,而不会复制到行号上去。

很多人都在想办法让它实现换行,但都卡在代码行号的问题上。我关注这个问题已经差不多一年了,今天终于有了个比较漂亮的解决办法。

首先,强制给代码部分换行的CSS还是要写的:

body .syntaxhighlighter .line
{
    white-space: pre-wrap !important;
}

这段CSS换行的前提是,pre标签的外边一定要有一个固定宽度的容器对象。比如一个600px宽度的div就可以。

然后,我们需要一段JQuery,用来计算被换行的代码显示在页面上的高度,然后赋值给它的行标。这段代码是国外一个论坛上找的,但我测试的时候发现它有点小问题,我的环境是JQuery1.7+Firefox15,我顺便做了一个修正,全部代码如下:

$(function () {
    // Line wrap back
    var shLineWrap = function () {
        $('.syntaxhighlighter').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
                console.debug($gutterLine.height(), height, $gutterLine.text(), $codeLine);
            });
        });
    };

    // Line wrap back when syntax highlighter has done it's stuff
    var shLineWrapWhenReady = function () {
        if ($('.syntaxhighlighter').length === 0) {
            setTimeout(shLineWrapWhenReady, 10);
        }
        else {
            shLineWrap();
        }
    };

    // Fire
    shLineWrapWhenReady();
});

现在,行号的高度就能和代码的高度保持一致了。