52

Webサイトにコードを表示しようとしていますが、空白のインデントを正しく保持するのに問題があります。

たとえば、次のスニペットが与えられます。

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

これは、ブラウザに次のように表示されます。

Here is my code:

     def some_funtion
       return 'Hello, World!'
     end

次のように表示したい場合:

Here is my code:

def some_funtion
 return 'Hello, World!'
end

違いは、HTMLpreタグの現在のインデントレベルがコードのインデントに追加されていることです。私は静的なウェブサイトジェネレーターとしてnanocを使用しており、構文の強調表示も追加するためにgoogleprettifyを使用しています。

誰かが何か提案をすることができますか?

4

11 に答える 11

24

PRE表示されているとおりに空白を保持することを目的としています (white-space書式設定コードをサポートするのに十分な柔軟性がない CSS で変更されない限り)。

フォーマットは保持されますが、PREタグの外側のすべてのインデントも保持されます。タグの場所を出発点として使用する空白の保存があるとよいでしょう。

ここに画像の説明を入力

コンテンツは宣言どおりにフォーマットされPREますが、ドキュメント内のタグの位置によって生じる余分な先頭の空白は削除されます。

ここに画像の説明を入力

ドキュメント アウトラインのインデントによって発生する余分な空白を削除したいという問題を解決するために、次のプラグインを思い付きました。このコードは、PRE タグ内の最初の行を使用して、純粋にドキュメントのインデントが原因でどの程度インデントされたかを判断します。

このコードは、IE7、IE8、IE9、Firefox、および Chrome で機能します。Prettifyライブラリを使用して簡単にテストし、保存された書式設定ときれいな印刷を組み合わせました。内の最初の行が、PRE無視するインデントのベースライン レベルを実際に表していることを確認してください (または、プラグインをよりインテリジェントに変更できます)。

これは大まかなコードです。間違いを見つけたり、思い通りに動作しない場合は、修正/コメントしてください。ただ反対票を投じないでください。私が抱えていた問題を修正するためにこのコードを書きましたが、積極的に使用しているので、できるだけしっかりしたものにしたいと思います!

/*!
*** 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 );

このプラグインは、標準の jQuery セレクターを使用して適用できます。

<script>
    $( function() { $("PRE").prettyPre(); } );
</script>
于 2012-02-19T21:02:05.603 に答える
5

JavaScriptでこれを行うことができました。Internet Explorer 9 と Chrome 15 で動作しますが、古いバージョンはテストしていません。Firefox 11 でのサポートouterHTMLが追加された場合 (こちらを参照) で動作するはずですが、Web 上で利用可能なカスタム実装がいくつかあります。読者のための演習は、末尾のインデントを取り除くことです (それを終了してこの回答を更新する時間ができるまで)。

また、簡単に編集できるように、これをコミュニティ wiki としてマークします。

タブをインデントとして使用するように例を再フォーマットするか、スペースで動作するように正規表現を変更する必要があることに注意してください。

<!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>
于 2011-12-14T13:20:42.947 に答える
3

これは、4 行の JavaScript で実行できます。

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>

于 2015-07-31T20:21:20.247 に答える
3

要素の を変更しても問題ない場合innerHTML:

与えられた:

<pre>
  <code id="the-code">
    def some_funtion
      return 'Hello, World!'
    end
  </code
</pre>

次のようにレンダリングされます。


    def some_funtion
      return 'Hello, World!'
    end

次のバニラ JS:

// get block however you want.
var block = document.getElementById("the-code");

// remove leading and trailing white space.
var code = block.innerHTML
                .split('\n')
                .filter(l => l.trim().length > 0)
                .join('\n');

// find the first non-empty line and use its
// leading whitespace as the amount that needs to be removed
var firstNonEmptyLine = block.textContent
                             .split('\n')
                             .filter(l => l.trim().length > 0)[0];

// using regex get the first capture group
var leadingWhiteSpace = firstNonEmptyLine.match(/^([ ]*)/);

// if the capture group exists, then use that to
// replace all subsequent lines.
if(leadingWhiteSpace && leadingWhiteSpace[0]) {
  var whiteSpace = leadingWhiteSpace[0];
  code = code.split('\n')
             .map(l => l.replace(new RegExp('^' + whiteSpace + ''), ''))
             .join('\n');
}

// update the inner HTML with the edited code
block.innerHTML = code;

結果は次のとおりです。

<pre>
  <code id="the-code">def some_funtion
  return 'Hello, World!'
end</code>
</pre>

そして、次のようにレンダリングされます:

def some_funtion
  return 'Hello, World!'
end
于 2020-05-19T16:33:15.980 に答える
2

また、haml を使用している場合は、preserveメソッドを使用できることもわかりました。例えば:

preserve yield

これにより、生成された空白が保持されyieldます。これは通常、コード ブロックを含むマークダウンです。

于 2015-04-01T19:12:36.923 に答える
2

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

于 2016-04-20T06:15:25.163 に答える
2

pre働き方や働き方を変えるよりも、もっと具体的なことを考えてみようと思いましたcode。だから私は最初の改行文字を取得するためにいくつかの正規表現を作成しました\n(可能性のある空白が先行します-これ\s*は、コード行の終わりと改行文字の前の余分な空白をクリーンアップするために使用されます(あなたのものに気づきました))タブまたはそれに続く空白文字[\t\s]*(つまり、タブ文字、空白文字 (0 以上)) を変数に設定し、その値を変数に設定します。次に、その変数を正規表現置換関数で使用して、そのすべてのインスタンスを検索し、\n(改行) に置き換えます。 2 行目 ( gets が設定されている場所) にはグローバル フラグ (正規表現patternの後の a) がありません。g\n改行文字を変更し、pattern変数をその値に設定します。したがって、改行の後に 2 つのタブ文字が続く場合、 の値patternは技術的に\n\t\tは になります。これは、その要素内のすべての\n文字が見つかった場所で置き換えられpre code(各関数を実行しているため)、次のように置き換えられます。\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>

于 2015-07-31T21:00:52.267 に答える
0

これは面倒ですが、コードの折りたたみが重要な場合は機能します。

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

あなたのCSSで、

    pre { margin:0 }

vim では、通常どおりコードを記述してから実行します。

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

各行が機能します。

于 2015-04-03T19:16:14.530 に答える
-3

pre タグは、本文の書き込み中に使用したすべての空白を保持します。通常、 pre を使用しない場合、テキストは通常​​どおり表示されます... (HTML により、ブラウザーはこれらの空白を無視するようになります) ここでこれを試してください。段落タグを使用しました。出力:-

これが私のコードです:

def some_function

  return 'Hello, World!'

終わり

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

于 2014-01-29T20:53:00.627 に答える