top

「改行を変換」で<pre>を使うコツ

小技ですが…。
最近、MTタグのサンプルなどを囲むHTMLタグを<blockquote>から<pre>に変更しています。なんでこれまで<blockquote>を使ってきたのかというと、MTを使い始めた頃、管理画面に付いてるボタンが<blockquote>だったので、そのまま習慣で何となく使い続けてきてしまった、ただそれだけです(汗)。けど、自分で<pre>ボタンを追加できたので、<blockquote>よりはまだ<pre>の方がよかろうということで、少しずつ修正中です。

ここから本題。私はふだん記事書きには「改行を変換」を使っています。<pre>は空白も一緒にコードをそのままの形で表示してくれるので便利なんですが、「改行を変換」にはちょっと癖がありまして、時に<pre>内で変な変換をされることがあります。例えば以下のサンプルの場合。これを<pre>で囲むと…。

.layout-twt #alpha {
    left: 190px;
    width: 560px;
}

.layout-twt #beta {
    left: -560px;
    width: 190px;
}

こんなふうに表示されちゃいます。↓ 途中から間延びしてるんですが…。

080818.gif

ソースを見てみると、こんな感じになっています。

<pre>.layout-twt #alpha {
    left: 190px;
    width: 560px;
}

<p>.layout-twt #beta {<br />
    left: -560px;<br />
    width: 190px;<br />
}</pre></p>

途中まではいいのですが、真ん中の空行のせいで「以下は段落」とみなされるのか、<pre>の中に<p>が割り込んできて<br />まで勝手に入った上にタグの閉じ方もおかしい(^^;。これを正しく<pre>内には余計な<p><br />を入れさせないにはどうしたらいいか。答えは実は意外と簡単です。

080818_2.gif

空行になっている部分(青丸部分)に半角空白を1つだけ入れておきます。

これだけでMTくんは空行とは見なさず、文字が続いていると解釈してくれるので、最後まで<pre>内には余計なものは入らずに済みます。

以下が「改行を変換」で正しく出力された<pre>です。

.layout-twt #alpha {
    left: 190px;
    width: 560px;
}
 
.layout-twt #beta {
    left: -560px;
    width: 190px;
}

空行部分に半角空白が入っていても、見た目にもコードにも何も問題はないですから、これで一件落着。


■おまけ:「改行を変換」のHTMLタグの挙動について
「改行を変換する」は改行は<br />、空行を目安に段落は<p>に自動変換してくれる便利なフォーマットです。MTが出来た頃からある最もスタンダードなフォーマットだと思います。ところで、「改行を変換」でも意図的に<p>を入れるなどしてHTMLタグを使うことが出来ます。その場合、「改行を変換」特有の動きについて知っておくと使いやすくなります。

●ブロックタグ内では自動変換は機能しなくなる
基本的にブロックタグ(<p>、<div>、<blockquote>など)内は「なし」フォーマットを選んだ時と同じ状態になります。MTの自動変換が働かなくなるので、好きなタグで自由に制御することが出来るようになります。例えば、<textarea>を<p>で囲むことによって<textarea>内に<br />を出させなくする、というふうに使うことが出来ます。

●ブロックタグ内では空行は作らないように注意。
気を付けたいのがここ。空行があると、そこで段落と見なされ、自動変換機能が働きだすので、<pre>タグの例のように空行以降がおかしなことになってしまいます。
*どうしても空行を作りたい時は、<pre>のように半角空白で埋めて空行状態ではなくなるようにします。

●ブロックタグと文字の間には空行を入れる。
ブロックタグの周囲の挙動。以下のように文字がブロックタグとくっついていると、ブロックタグを含む全体が段落と見なされて<p>で囲われてしまいます。

悪い例(あああ~ううう までが<p>で囲まれるので、<p>の中に<div>が入ってしまう)

あああ
<div><p>いいい</p>
<p>いいい</p></div>
ううう
→出力ソース→ <p>あああ<br />
<div><p>いいい</p><br />
<p>いいい</p></div><br />
ううう</p>

いい例(正しく変換される)

あああ

<div><p>いいい</p>
<p>いいい</p></div>

ううう
→出力ソース→ <p>あああ</p>

<div><p>いいい</p>
<p>いいい</p></div>

<p>ううう</p>

コツが分かれば「改行を変換」でも問題なくHTMLタグを使うことが出来ます。

alt_tmplで記事投稿画面に文字挿入ボタンをつける

自分のための覚え書きですが、試してみたいという方がおられましたらご自由にどうぞ~。ただし自己責任でお願い致しますです。

込み入ったカスタマイズ系の記事はExpression Webで下書きしているので、MTの管理画面にはそんなに本格的なWYSIWYGエディタは必要ないんですが、軽い覚え書きや気軽に書きたい日記、雑記系では直接MTの管理画面から気分のままに打ち込むことも多いので、そんな時ちょっとした補助ボタンがあるといいなあと思うことがあります。

しかし。タグ挿入支援とか色文字とか管理画面にボタンを追加してくれるプラグインはいろいろありますが、私の場合は文字を<p></p>とかのHTMLタグで囲むのではなくて、単に文字列(オリジナルのclassとか、よく使うstyleとか)だけをカーソルの位置にポンと入れたいだけなんですよね…。

080800_1.gif

←それで、alt_tmplを使って、記事入力画面の下によく使うスタイルなどを並べていたんですが、これだと文字を選択してから入力画面にドラッグするという手間がかかるので少し面倒くさい。押すだけで一発で入ってくれたら便利でいいのになーと思っていました。
たまたまコメントにエンコードボタンで、自分でも応用できそうなjavascriptを見つけたので、それを使って一発で挿入できるボタンに改造してみました。alt_tmplを使っているのでプラグインではないです。

■ 本題:alt_tmplで記事投稿画面に文字挿入ボタンをつける
alt_tmplについてはこちらを参照。要するに管理画面のコピーを作って、本体は触らずにコピーの方を改造するというものです。

1.ボタンの準備
この画像を 適当なところにアップ。とりあえず(自分にとって)必要最低限のボタンを用意。

2.スクリプトの準備
以下の内容をentry_button.tmplというファイル名で作成。文字コードは使っているブログに合わせます。

<script type="text/javascript">
// 選択用
function tagButtonA(tag, obj) {
var target = document.getElementById(obj);
var pos = getAreaRange(target);
var val = target.value;
var range = val.slice(pos.start, pos.end);
var beforeNode = val.slice(0, pos.start);
var afterNode = val.slice(pos.end);
var insertNode;
if (range || pos.start != pos.end) {
insertNode = '<' + tag + '>' + range + '</' + tag + '>';
target.value = beforeNode + insertNode + afterNode;
}
else if (pos.start == pos.end) {
insertNode = '<' + tag + '>' + '</' + tag + '>';
target.value = beforeNode + insertNode + afterNode;
}
}
 
// 挿入用
function tagButtonB(tag, obj) {
var target = document.getElementById(obj);
var pos = getAreaRange(target);
var val = target.value;
var beforeNode = val.slice(0, pos.start);
var afterNode = val.slice(pos.end);
var insertNode;
insertNode = '' + tag + '';
target.value = beforeNode + insertNode + afterNode;
}
 
// 実体参照変換用
function encodeButton(obj) {
var target = document.getElementById(obj);
var pos = getAreaRange(target);
var val = target.value;
var range = val.slice(pos.start, pos.end);
var beforeNode = val.slice(0, pos.start);
var afterNode = val.slice(pos.end);
var insertNode;
if (range || pos.start != pos.end) {
range = range.replace(/&/g, "&amp;");
range = range.replace(/</g, "&lt;");
range = range.replace(/>/g, "&gt;");
range = range.replace(/"/g, "&quot;");
insertNode = '' + range + '';
target.value = beforeNode + insertNode + afterNode;
}
}
 
function getAreaRange(obj) {
var pos = new Object();
if (isIE) {
obj.focus();
var range = document.selection.createRange();
var clone = range.duplicate();
clone.moveToElementText(obj);
clone.setEndPoint( 'EndToEnd', range );
pos.start = clone.text.length - range.text.length;
pos.end = clone.text.length - range.text.length + range.text.length;
}
else if(window.getSelection()) {
pos.start = obj.selectionStart;
pos.end = obj.selectionEnd;
}
return pos;
}
var isIE = (navigator.appName.toLowerCase().indexOf('internet explorer')+1?1:0);
</script>
<style type="text/css">
.tagbutton { margin:-15px 0px 15px 0px; }
.tagbutton button { background-color: #FFFFFF; border: none; padding:0px; }
</style>
 
<div class="tagbutton">
<button type="button" onclick="tagButtonA('pre','editor-content-textarea');" title="pre"><img src="ボタンのアドレス/pre.gif" width="22" height="22" /></button>
<button type="button" onclick="encodeButton('editor-content-textarea');" title="実体参照"><img src="ボタンのアドレス/enc.gif" width="22" height="22" /></button>
<button type="button" onclick="tagButtonB('&lt;br style=&quot;clear: both&quot; /&gt;','editor-content-textarea');" title="回り込み解除"><img src="ボタンのアドレス/clear.gif" width="22" height="22" /></button>
<button type="button" onclick="tagButtonB('target=&quot;_blank&quot;','editor-content-textarea');" title="別窓"><img src="ボタンのアドレス/blank.gif" width="22" height="22" /></button>
</div>

ボタン画像のアドレス(赤字の部分)は各自の環境に合わせて。

3.alt_tmplの準備
MTのファイルの中にalt_tmplというフォルダがありますが、中身は空っぽです。そこにcmsフォルダを作成して、tmpl/cms/にあるedit_entry.tmplのコピーを置きます。つまり、alt_tmplフォルダの中にtmpl/cms/edit_entry.tmplと同じ環境を作るわけです。
そして、edit_entry.tmplのコピーと同じ位置に先ほど作ったentry_button.tmplを置きます。
080817.gif
alt_tmpl/cms/以下にedit_entry.tmplのコピーとentry_button.tmplの2つのファイルが入ったことになります。

4.alt_tmpl/cms/edit_entry.tmplの改造
1027行目の辺り(4.1なら1054行目辺り)にある<mt:include name="include/editor.tmpl">の下に以下を追加。

<mt:include name="entry_button.tmpl">

edit_entry.tmplコピーの改造部分はこの一行だけです。これで管理画面を開くと、テキスト入力フォームの下に以下のボタンが出てきます。あとはクリックするだけで文字が入ります。

080800_2.gif

説明とか。
:選択した文字列を<pre></pre>で囲みます。HTML系でこれだけは欲しかったので入れました。
:実体参照変換ボタン。選択した文字中の「<」「>」「&」「"」を実体参照に変換します。自分には必須。
:回り込み解除ボタン。カーソルの位置に<br style="clear: both" />と入ります。floatで画像に文字を回り込みさせている時、任意の位置で回り込みを解除して画像の下から文を始めたい時に必須。
:別窓用。カーソルの位置にtarget="_blank"と入ります。別窓表示させたいリンクに。

・entry_button.tmplの中身はjavascriptなので、javascriptが分かる人は好きなように変えてやって下さい。
・entry_button.tmplの中身はMTのシステムに依存しない独立した内容になっているので、フォームのid(青字の部分)さえ合っていればどのバージョンでも動くと思います(試しに3.3のedit_entry.tmplに突っ込んでみたところ動作しました)。

<注>基本的に「改行を変換する」「なし」で使っている場合向けです。リッチテキストで使う場合はHTMLモードにして下さい。WYSIWYGモードでは動作しません。
VistaのIE7とFirefoxでしか動作確認していません。自分用なので、それ以外で動かなくてもサポートしません(汗)。すみません。

MTをバージョンアップした時は?
alt_tmpl/cms/edit_entry.tmplを 新しいバージョンのedit_entry.tmplに差し替え、該当箇所に
<mt:include name="entry_button.tmpl">
を入れるだけです。ちょっと手間はありますが、バージョンアップのたびに動かなくなって困るということはないかと。

管理画面に機能追加するには、プラグインの他にこんな方法もありますね、てことで。