13

在我的 HTML 源代码中,我有一个如下代码块(我在此页面上使用 showdown 和 highlight.js):

<pre><code class="cpp">
double myNumber = (double)4;
</code></pre>

我的问题是第一个换行符仍然是“代码”块的一部分。这可能是因为封闭的“pre”块,但我需要它,因为 highlight.js 需要它(显然 HTML5 标准也推荐它)。代码呈现如下(注意前导换行符):

在此处输入图像描述

所以我的问题是,使用 css、javascript 或 jquery,如何从像这样的“代码”块中删除前导或尾随换行符?

4

6 回答 6

16

你可以使用这个技巧:

pre:first-line {
    line-height: 0;
}
于 2013-02-19T01:59:34.697 回答
4

这是使用 Javascript 的另一种方法,它也解决了这个问题:

<script>
    window.onload = function (){
        // remove leading linebreaks from code blocks.
        var pre = document.getElementsByTagName("code");
        for (var i = 0, len = pre.length; i < len; i++) {
            var text = pre[i].firstChild.nodeValue;
            pre[i].firstChild.nodeValue = text.replace(/^\n+|\n+$/g, "");
        }
    }
</script>

其他人发布了这个,然后删除了他们的答案,但我认为它值得保留。

于 2013-02-20T22:31:33.073 回答
3

这就是pre默认情况下的工作方式:它尊重换行符和空格。如果您不想渲染换行符,则必须将其删除。如果您关心源的外观,请直接将其从源中删除或将其注释掉。

http://jsfiddle.net/VL8tG/

<pre><code class="cpp"><!--
-->double myNumber = (double)4;<!--
--></code></pre>
于 2013-02-19T01:06:55.000 回答
3

我只是在荧光笔开始之前手动删除它们。

const trimLine = node => 
  node.firstChild.nodeValue = node.firstChild.nodeValue.replace(/^\n+|\n+$/g, "");



window.onload = function () {

  Array.prototype.slice
      .call(document.getElementsByTagName("code"), 0)
      .map(trimLine);

  hljs.initHighlightingOnLoad();

}

于 2016-07-12T22:03:14.523 回答
2

演示:http: //jsfiddle.net/WjVVs/4/

在 PC 上使用 Chrome 和 FF 进行了测试。将插件应用于元素时,它在 IE 9 中不起作用code(应用于元素时似乎可以正常工作pre)。我找不到合适的解决方法,但请随时发表评论/更新。

这是另一个答案的修改版本。这个插件试图去除由文档的自然流动引起的额外缩进。我已经对其进行了修改,使其在前导空白方面更加智能。

如果它工作正常,您应该会看到如下内容:

在此处输入图像描述

用法

$("code").prettyPre(); // any selector here

带有前导空格和额外缩进的 HTML

<div>
        <pre><code class="cpp">
           double myNumber = (double)4;

           // another line

           // another line

                // this is purposely indented further
                for( var i = 0; i < 100; i++ ){

                }            

        </code></pre>
</div>

插入

(function( $ ) {
    $.fn.prettyPre = function( method ) {

        var defaults = {
            ignoreExpression: /\s/ // what should be ignored?
        };

        var methods = {
            init: function( options ) {
                this.each( function() {
                    var context = $.extend( {}, defaults, options );
                    var $obj = $( this );
                    var usingInnerText = true;
                    var text = $obj.get( 0 ).innerText;

                    // some browsers support innerText...some don't...some ONLY work with innerText.
                    if ( typeof text == "undefined" ) {
                        text = $obj.html();
                        usingInnerText = false;
                    }

                    // use the first line as a baseline for how many unwanted leading whitespace characters are present
                    var superfluousSpaceCount = 0;
                    var pos = 0;
                    var currentChar = text.substring( 0, 1 );

                    while ( context.ignoreExpression.test( currentChar ) ) {
                        if(currentChar !== "\n"){
                            superfluousSpaceCount++;
                        }else{
                            superfluousSpaceCount = 0;
                        }

                        currentChar = text.substring( ++pos, pos + 1 );
                    }

                    // split
                    var parts = text.split( "\n" );
                    var reformattedText = "";

                    // reconstruct
                    var length = parts.length;
                    for ( var i = 0; i < length; i++ ) {

                        // remove leading whitespace (represented by an empty string)
                        if(i === 0 && parts[0]=== ""){
                            continue;   
                        }

                        // cleanup, and don't append a trailing newline if we are on the last line
                        reformattedText += parts[i].substring( superfluousSpaceCount ) + ( i == length - 1 ? "" : "\n" );
                    }

                    // modify original
                    if ( usingInnerText ) {
                        $obj.get( 0 ).innerText = reformattedText;
                    }
                    else {
                        // This does not appear to execute code in any browser but the onus is on the developer to not 
                        // put raw input from a user anywhere on a page, even if it doesn't execute!
                        $obj.html( reformattedText );
                    }
                } );
            }
        }

        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ) );
        }
        else if ( typeof method === "object" || !method ) {
            return methods.init.apply( this, arguments );
        }
        else {
            $.error( "Method " + method + " does not exist on jQuery.prettyPre." );
        }
    }
} )( jQuery );
于 2013-02-18T23:21:06.037 回答
1

这些函数使用一个类(添加到pre)来删除前导和尾随空格

function removeWhitespace(indent) {
  // Get a list of all elements that need whitespace removed by indent value (will have class `indent-X`)
  // List may be 0 long - loop simply doesn't run
  var preElements = document.getElementsByClassName('indent-'+indent);
  for (i = 0; i < preElements.length; i++) {
    preElements[i].innerHTML = preElements[i].innerHTML.split('\n'+' '.repeat(indent)).join('\n').split('\n'+' '.repeat(indent-2)+'</code>').join('</code>').split("\n").slice(1,-1).join("\n");
    //split('\n'+' '.repeat(indent)).join('\n') -- Split at every newline followed by X spaces. Then join together with the newlines.
    // .split('\n'+' '.repeat(indent-2)+'</code>').join('</code>') -- The lastline will have 2 less spaces, so remove those, and the newline at the end. Add the tag back in.
    //.split("\n").slice(1,-2).join("\n"); -- Remove the first and last lines.
  }
}

function removeWhitespaces() {
  // Loop over all indents, 2 to 40
  for (indent = 2; indent <= 40; indent+=2) {
    removeWhitespace(indent);
  }
}

只需将要删除的空格数量indent-X的类添加到.Xpre

JSFiddle

function removeWhitespace(indent) {
  // Get a list of all elements that need indent removed by indent value (will have class `indent-X`)
  // List may be 0 long - loop simply doesn't run
  var preElements = document.getElementsByClassName('indent-' + indent);

  for (i = 0; i < preElements.length; i++) {
    preElements[i].innerHTML = preElements[i].innerHTML.split('\n' + ' '.repeat(indent)).join('\n').split('\n' + ' '.repeat(indent - 2) + '</code>').join('</code>').split("\n").slice(1, -2).join("\n");
    //split('\n'+' '.repeat(indent)).join('\n') -- Split at every newline followed by X spaces. Then join together with the newlines.
    // .split('\n'+' '.repeat(indent-2)+'</code>').join('</code>') -- The lastline will have 2 less spaces, so remove those, and the newline at the end. Add the tag back in.
    //.split("\n").slice(1,-1).join("\n"); -- Remove the first and last lines.

    // Remove the clickme element.
    document.getElementById('clickme').innerHTML = '';
  }
}

function removeWhitespaces() {
  // Loop over all indents, 2 to 40
  for (indent = 2; indent <= 40; indent += 2) {
    removeWhitespace(indent);
  }
}
.indent-14 {
  background-color: #ccc;
}
<body>
  <div id="clickme" onclick="removeWhitespaces()">
    Click Me
  </div>
  <pre class="indent-14">
    <code>
              function createCORSRequest(method, url) {
                var request = new XMLHttpRequest();
                if ('withCredentials' in request) {
                  request.open(method, url, true);
                } else if (typeof XDomainRequest != 'undefined') {
                  request = new XDomainRequest();
                  request.open(method, url);
                } else {
                  request = null;
                }
                return request;
              }
    </code>
  </pre>
</body>

于 2016-06-11T16:04:21.710 回答