How can I ignore leading and trailing linebreaks within an html “code” block using css, javascript or jquery?

前端 未结 6 929
伪装坚强ぢ
伪装坚强ぢ 2021-02-19 18:59

In my HTML source code, I have a code block like the following (I use showdown and highlight.js on this page):


double myNum         


        
相关标签:
6条回答
  • 2021-02-19 19:34

    I just remove them manually before the highlighter starts.

    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();
    
    }

    0 讨论(0)
  • 2021-02-19 19:36

    You could use this hack:

    pre:first-line {
        line-height: 0;
    }
    
    0 讨论(0)
  • 2021-02-19 19:49

    These functions use a class (added to the pre) to remove leading and trailing whitespace

    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);
      }
    }
    

    Simply add the class indent-X where X is the amount of whitespace you want to remove to the pre.

    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>

    0 讨论(0)
  • 2021-02-19 19:51

    Here's another approach using Javascript that also solves the problem:

    <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>
    

    Someone else posted this, then deleted their answer, but I thought it was worth preserving.

    0 讨论(0)
  • 2021-02-19 19:52

    That's how pre works by default: it honors line breaks and whitespace. If you don't want the newline to render, then you have to remove it. Either outright remove it from the source or comment it out if you care how the source looks.

    http://jsfiddle.net/VL8tG/

    <pre><code class="cpp"><!--
    -->double myNumber = (double)4;<!--
    --></code></pre>
    
    0 讨论(0)
  • 2021-02-19 19:56

    Demo: http://jsfiddle.net/WjVVs/4/.

    Tested with Chrome and FF on the PC. It does not work in IE 9 when the plugin is applied to a code element (it appears to work fine when applied to a pre element). I can't find a suitable workaround, but feel free to comment/update.

    This is a modified version from another answer. This plugin attempts to remove extra indentation caused by the natural flow of the document. I've modified it to be smarter about leading whitespace.

    If it works correctly, you should see something like:

    enter image description here

    Usage

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

    HTML with leading whitespace and extra indentation

    <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>
    

    Plugin

    (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 );
    
    0 讨论(0)
提交回复
热议问题