webentwicklung-frage-antwort-db.com.de

Wie kann der Leerraumeinzug von in HTML-Tags eingeschlossenem Text beibehalten werden, wobei die aktuelle Einzugsebene des Tags im Text nicht berücksichtigt wird?

Ich versuche, meinen Code auf einer Website anzuzeigen, aber ich habe Probleme, die Whitespace-Einrückung korrekt zu erhalten.

Zum Beispiel gegeben der folgende Ausschnitt:

<html>
 <body>
   Here is my code:
   <pre>
     def some_funtion
       return 'Hello, World!'
     end
   </pre>
 <body>
</html>

Dies wird im Browser als angezeigt:

Here is my code:

     def some_funtion
       return 'Hello, World!'
     end

Wann möchte ich es als angezeigt werden:

Here is my code:

def some_funtion
 return 'Hello, World!'
end

Der Unterschied besteht darin, dass die aktuelle Einrückungsebene des HTML-Pre-Tags zur Einrückung des Codes hinzugefügt wird. Ich verwende nanoc als statischen Website-Generator und benutze Google Prettify, um auch Syntax-Hervorhebungen hinzuzufügen.

Kann jemand irgendwelche Vorschläge anbieten? 

41
Michael Barton

PRE soll Leerzeichen genau so beibehalten, wie sie angezeigt werden (sofern sie nicht durch white-space in CSS geändert werden, da sie nicht ausreichend flexibel ist, um Formatierungscode zu unterstützen).

Vor

Die Formatierung wird beibehalten, aber alle Einrückungen außerhalb des Tags PRE. Es wäre schön, wenn die Whitespace-Bewahrung die Position des Tags als Ausgangspunkt verwendet.

enter image description here

Nach dem

Die Inhalte werden weiterhin wie deklariert formatiert, aber der durch die Position des Tags PRE innerhalb des Dokuments verursachte übergeordnete Leerraum wird entfernt.

enter image description here

Ich habe mir das folgende Plugin ausgedacht, um das Problem zu lösen, überflüssigen Leerraum entfernen zu wollen, der durch die Einrückung der Dokumentumrisse verursacht wird. Dieser Code verwendet die erste Zeile innerhalb des PRE-Tags, um zu bestimmen, wie sehr er aufgrund der Einrückung des Dokuments eingerückt wurde.

Dieser Code funktioniert in IE7, IE8, IE9, Firefox und Chrome. Ich habe es kurz mit der Bibliothek Prettify getestet, um die konservierte Formatierung mit hübschem Druck zu kombinieren. Stellen Sie sicher, dass die erste Zeile in PRE tatsächlich die Basisebene des Einzugs darstellt, die Sie ignorieren möchten (oder Sie können das Plugin modifizieren, um intelligenter zu sein).

Dies ist ein grober Code. Wenn Sie einen Fehler finden oder nicht so funktionieren, wie Sie möchten, korrigieren Sie bitte/kommentieren Sie ihn nicht einfach. Ich habe diesen Code geschrieben, um ein Problem zu beheben, das ich hatte und bin aktiv Ich benutze es, damit ich es so fest wie möglich halten möchte!

/*!
*** prettyPre ***/

(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 currentChar = text.substring( 0, 1 );

                    while ( context.ignoreExpression.test( currentChar ) ) {
                        currentChar = text.substring( ++superfluousSpaceCount, superfluousSpaceCount + 1 );
                    }

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

                    // reconstruct
                    var length = parts.length;
                    for ( var i = 0; i < length; i++ ) {
                        // 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 );

Dieses Plugin kann dann mit einem standardmäßigen jQuery-Selektor angewendet werden:

<script>
    $( function() { $("PRE").prettyPre(); } );
</script>
22
Tim Medora

Einrücken mit Kommentaren

Da Browser Kommentare ignorieren, können Sie sie verwenden, um den Inhalt des pre-Tags einzurücken.

Lösung

<html>
  <body>
    <main>
      Here is my code with hack:
      <pre>
<!-- -->def some_function
<!-- -->  return 'Hello, World!'
<!-- -->end
      </pre>
      Here is my code without hack:
      <pre>
        def some_function
          return 'Hello, World!'
        end
      </pre>
    </main>
  <body>
</html>

HINWEIS: Ein Hauptwrapper wurde hinzugefügt, um ausreichend Platz für die Kommentare zu bieten.

Vorteile

  • Kein JavaScript erforderlich
  • Kann statisch hinzugefügt werden
  • Minification wirkt sich nicht auf die Einrückung aus und verringert die Dateigröße

Nachteile

  • Erfordert ein Minimum an Speicherplatz für die Kommentare
  • Nicht sehr elegant, wenn keine Build-Tools verwendet werden

Einrückung mit Knoten entfernen

Eine bessere Lösung ist das Entfernen des führenden Leerraums entweder durch den Build-Prozess oder den Back-End-Rendering-Prozess. Wenn Sie node.js verwenden, können Sie einen Stream verwenden, den ich geschrieben habe: predentation . Sie können jede Sprache verwenden, mit der Sie ein ähnliches Werkzeug erstellen möchten.

Vor

<html>
 <body>
   Here is my code:
   <pre>
     def some_function
       return 'Hello, World!'
     end
   </pre>
 </body>
</html>

Nach dem

<html>
 <body>
   Here is my code:
   <pre>
def some_function
  return 'Hello, World!'
end
   </pre>
 </body>
</html>

Vorteile

  • Nahtlose Möglichkeit, pre-Tags zu schreiben
  • Kleinere Größe der Ausgabedatei

Nachteile

  • Erfordert einen Erstellungsschritt in Ihrem Workflow
  • Behandelt nicht pre-Elemente mit white-space: pre, die von CSS hinzugefügt werden

Einrückung mit JavaScript entfernen

Diese Antwort sehen, um den Einzug mit JavaScript zu entfernen

Vorteile

  • Elemente können mit white-space: pre als Ziel ausgewählt werden

Nachteile

  • JavaScript kann deaktiviert werden
  • Leerzeichen erhöht die Dateigröße
12
Dale

Schaffte dies mit JavaScript. Es funktioniert in Internet Explorer 9 und Chrome 15, ältere Versionen habe ich nicht getestet. Es sollte in Firefox 11 funktionieren, wenn outerHTML unterstützt wird (siehe hier ). Inzwischen sind einige benutzerdefinierte Implementierungen im Web verfügbar. Eine Übung für den Leser besteht darin, die nachstehende Einrückung zu entfernen (bis ich mir die Zeit nehme, sie zu beenden und diese Antwort zu aktualisieren).

Ich werde dies auch als Community-Wiki für die einfache Bearbeitung kennzeichnen.

Bitte beachten Sie, dass Sie das Beispiel neu formatieren müssen, um Tabulatoren als Einzug zu verwenden, oder die Regex in Leerzeichen umwandeln.

<!DOCTYPE html>
<html>
    <head>
        <title>Hello, World!</title>
    </head>
    <body>
        <pre>
            &lt;html&gt;
                &lt;head&gt;
                    &lt;title&gt;Hello World Example&lt;/title&gt;
                &lt;/head&gt;
                &lt;body&gt;
                    Hello, World!
                &lt;/body&gt;
            &lt;/html&gt;
        </pre>
        <pre>
            class HelloWorld
            {
                public static int Main(String[] args)
                {
                    Console.WriteLine(&amp;quot;Hello, World!&amp;quot;);
                    return 0;
                }
            }
        </pre>
        <script language="javascript">
            var pre_elements = document.getElementsByTagName('pre');

            for (var i = 0; i < pre_elements.length; i++)
            {
                var content = pre_elements[i].innerHTML;

                var tabs_to_remove = '';
                while (content.indexOf('\t') == '0')
                {
                  tabs_to_remove += '\t';
                  content = content.substring(1);
                }

                var re = new RegExp('\n' + tabs_to_remove, 'g');
                content = content.replace(re, '\n');
                pre_elements[i].outerHTML = '<pre>' + content + '</pre>';
            }
        </script>
    </body>
</html>
5
Stijn

Dies kann in vier JavaScript-Zeilen erfolgen:

var pre= document.querySelector('pre');

//insert a span in front of the first letter.  (the span will automatically close.)
pre.innerHTML= pre.textContent.replace(/(\w)/, '<span>$1');

//get the new span's left offset:
var left= pre.querySelector('span').getClientRects()[0].left;

//move the code to the left, taking into account the body's margin:
pre.style.marginLeft= (-left + pre.getClientRects()[0].left)+'px';
 <body>
   Here is my code:
   <pre>
     def some_funtion
       return 'Hello, World!'
     end
   </pre>
 <body>

3
Rick Hitchcock

<script>
    $("pre[name='pre']").each(function () {
        var html = $(this).html()
        var blankLen = (html.split('\n')[0].match(/^\s+/)[0]).length
        $(this).html($.trim(html.replace(eval("/^ {" + blankLen + "}/gm"), "")))
    })
</script>
<div>
	<pre name="pre">
		1
			2
				3
	</pre>
</div>

2
屎克螂

Ich entschied mich für etwas Konkreteres, als die Arbeitsweise von pre oder code zu ändern. Also habe ich etwas Regex gemacht, um das erste Zeilenvorschubzeichen \n zu erhalten (vorangestelltes mögliches Whitespace - der \s* wird verwendet, um am Ende einer Codezeile und vor dem Newline-Zeichen (was Ihnen aufgefallen ist) zusätzlichen Whitespace zu bereinigen Tabulatorzeichen oder Whitespace-Zeichen folgen [\t\s]* (was Tabulatorzeichen, Whitespace-Zeichen (0 oder mehr) bedeutet, und setzen diesen Wert auf eine Variable. Diese Variable wird dann in der Regex-Ersetzungsfunktion verwendet, um alle Instanzen davon zu finden und durch \n zu ersetzen ( newline) Da die zweite Zeile (in der pattern gesetzt wird) nicht das globale Flag (eine g nach dem regulären Ausdruck) enthält, wird sie die erste Instanz des \n-Newline-Zeichens finden und die Variable pattern auf diesen Wert setzen Im Fall eines Zeilenvorschubs, gefolgt von 2 Tabulatorzeichen, wird der Wert von pattern technisch \n\t\t sein. Er wird ersetzt, wenn jedes \n-Zeichen in diesem pre code-Element gefunden wird (da es die einzelnen Funktionen durchläuft tion) und ersetzt durch \n

$("pre code").each(function(){
    var html = $(this).html();
    var pattern = html.match(/\s*\n[\t\s]*/);
    $(this).html(html.replace(new RegExp(pattern, "g"),'\n'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
    Here is some code:

    <pre><code>
        Here is some fun code!
        More code
          One tab
            One more tab
            
            Two tabs and an extra newline character precede me
    </code></pre>
</body>

1
ctwheels

Ich habe auch festgestellt, dass Sie, wenn Sie haml verwenden, die preserve-Methode verwenden können. Zum Beispiel:

preserve yield

Dadurch wird der Whitespace in der produzierten yield beibehalten, bei der es sich normalerweise um das Markdown handelt, das die Codeblöcke enthält.

1
Michael Barton

Das ist umständlich, aber es funktioniert, wenn die Code-Faltung für Sie wichtig ist:

        <pre>def some_funtion</pre>
        <pre>    return 'Hello, World!'</pre>
        <pre>end</pre>

In Ihrem CSS,

    pre { margin:0 }

Schreiben Sie in vim Ihren Code normal und führen Sie dann Folgendes aus:

    :s/\t\t\([^\n]\+\)/<pre>\1<\/pre>/

für jede Zeile würde funktionieren.

0
Paul Robert

Wenn Sie dies für einen Codeblock verwenden, wie:

<pre>
  <code>
    ...
  </code>
</pre>

Sie können css einfach so verwenden, um die große Menge an Leerraum auf der Vorderseite zu verschieben.

pre code {
  position: relative;
  left: -95px; // or whatever you want
}
0