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
違いは、HTML preタグの現在のインデントレベルがコードのインデントに追加されていることです。私はnanocを静的Webサイトジェネレーターとして使用し、google prettifyを使用して構文の強調表示も追加しています。
誰でも提案を提供できますか?
PRE
は、空白を表示どおりに保持することを目的としています(white-space
CSSでは、フォーマットコードをサポートするのに十分な柔軟性がありません。
Before
フォーマットは保持されますが、PRE
タグの外側のすべてのインデントも保持されます。タグの場所を開始点として使用する空白を保存しておくと便利です。
After
内容は依然として宣言どおりにフォーマットされますが、ドキュメント内の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>
JavaScriptでこれを行うことができました。 Internet Explorer 9で動作し、Chrome 15、古いバージョンはテストしていません。Firefox11では、outerHTML
のサポートが追加されたときに動作するはずです( here )一方、ウェブ上で利用可能なカスタム実装がいくつかあります。読者にとっての練習は、末尾のインデントを取り除くことです(終了してこの回答を更新するまで)。
また、簡単に編集できるように、これをコミュニティWikiとしてマークします。
タブをインデントとして使用するように例を再フォーマットするか、スペースを使用するように正規表現を変更する必要があることに注意してください。
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
</head>
<body>
<pre>
<html>
<head>
<title>Hello World Example</title>
</head>
<body>
Hello, World!
</body>
</html>
</pre>
<pre>
class HelloWorld
{
public static int Main(String[] args)
{
Console.WriteLine(&quot;Hello, World!&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>
これは、次の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>
<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>
pre
またはcode
の動作を変更するよりも具体的なものを思いつくことにしました。そこで、最初の改行文字\n
を取得するために正規表現を作成しました(可能性のある空白文字が前に付きます-\s*
は、コード行の最後で改行文字(あなたが持っていることに気づいた))、それに続くタブまたは空白文字を見つけます[\t\s]*
(タブ文字、空白文字(0以上)を意味し、その値を変数に設定します。その変数は、正規表現置換関数で使用されます。そのすべてのインスタンスを見つけて、\n
(改行)に置き換えます。2行目(pattern
が設定される)にはグローバルフラグ(正規表現の後の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>
また、hamlを使用している場合は、preserve
メソッドを使用できることもわかりました。例えば:
preserve yield
これにより、生成されたyield
の空白が保持されます。これは通常、コードブロックを含むマークダウンです。
これは面倒ですが、コードの折りたたみが重要な場合に機能します。
<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>/
各行で機能します。
次のようなコードブロックでこれを使用している場合:
<pre>
<code>
...
</code>
</pre>
このようなcssを使用するだけで、前面の大量の空白を相殺できます。
pre code {
position: relative;
left: -95px; // or whatever you want
}