ブログ記事でコード表示をする方法

ネットでプログラムのソースコードを紹介する場合、自分でサイトを作っている場合は、コード表示用のプラグイン「Syntax Highlighter」が使えます。 しかし、アメブロなどブログ上ではこの様なプラグインは使えない場合が殆どです。

 

そこで、「pre」枠をHTML編集で書き込んで、そこにソースコードをペーストして、コード紹介が出来るお膳立てをします。

 

この方式の詳細は以下のページに纏めているので、参照ください。

 

    アメーバブログ上でコード掲載をする 

 

ここでは、最初に簡単にその手順を纏めておきます。

 

 

❶ ブログ記事上の「pre」ブロックのCSS修飾を指定

「pre」ブロックを書き込む前に、前もって記事上で「pre」ブロックが見易いデザインになる様にCSS修飾をしておきます。 これは、各種のブラウザで見た場合にも、遜色ない表示とするためには、あった方が良い指定です。

 

CSS編集用デザインでない公式スキンを使用している場合は、以下のコードをフリースペースに追加します。(下のコードは、途中で改行すると無効になります)

 

<style>pre{font-size:1em;font-family:inherit;word-wrap:normal;overflow:visible}</style>

 

CSS編集用デザインのスキンの場合は、上のフリースペース追記でも良いですが、スキンCSSに直接以下の項目を追加しても同じ結果です。

 

pre {
    font-size: 1em;
    font-family: inherit;
    word-wrap: normal;
    overflow: visible; }

 

 

❷ 記事中にHTML編集で「pre」ブロックを記入する

記事中で、コード表示枠(preブロック)を作るには、HTML表示に移動し、HTML編集枠で以下のコードを記述します。

 

<div style="background:#fafafa; border:1px solid #aaa;overflow-y:hidden; max-width:660px; padding:0 30px">
<pre style="white-space:pre">

~~~ ここにコードを記述 ~~~

</pre></div>

 

「style=""」で色々と指定(インライン指定)してますが、これはスマホから見た場合も考慮したからです。 アメブロの場合は、スマホ表示はインライン指定を使う以外に修飾する方法がありません。

 

上側の2行は「div」「pre」の入れ子のブロックを作るもので、下側の1行はその終結タグです。 この間に表示させたいソースコードを貼り付けますが、「HTMLコード」は通常表示編集枠でペーストが必須で、「CSSコード」はHTML編集枠からのペーストが良い結果になります。

 

 

「pre」ブロックを記入する妥当な方法

上の ❷ の記入は、コードが長いので私は下の4個のパーツに分けて、IMEの語句登録して入力しています。 読みはみな「ぷり」です^^;

 

(1)  <div style="background:#fafafa; border:1px solid #aaa;">

(2)  overflow-y:hidden; max-width:660px; padding:0 30px

(3)  <pre style="white-space:pre">

(4)  </pre></div>

 

他に、サンプル置き場の記事を作り、雛形の空の「pre」ブロックを置いて、必要になったらコピー&ペーストするという方法があります。 また、メモ帳にHTMLコードの雛形を置いておく方法もあります。 私は、探しに行くのが邪魔臭いので、IME登録をしているわけです。

 

慣れるとたいした事はないですが、「HTML表示」に移動してこの書き込みをし、再び「通常表示」に戻ってコードをペーストするというのは、少々手間です。 そういう作業を簡単にするために「Both-WH」が必要になったのですが、今回はこの移動自体を不要にするスクリプトを作りました。 ここからが、このページの本題です。

 

 

 

「pre」ブロックを自動記入するスクリプト

 」のアイコンを記入するスクリプトは、通常表示の編集枠のカーソル位置で、<i>タグを記入します。 これは単純な文字の記入ではなく、HTMLで「Node」を新しく作り埋め込んでいます。「div」「pre」のブロックの埋め込みも、この演繹で可能です。 以下は、その部分のスクリプトです。

 

    editor_iframe = document.querySelector('.cke_wysiwyg_frame');
    iframe_doc = editor_iframe.contentWindow.document;
    selection = iframe_doc.getSelection();
    range = selection.getRangeAt(0);
    insert_node = iframe_doc.createElement("div");
    insert_node.setAttribute("style", "background:#fafafa; border:1px solid #aaa;overflow-y:hidden; max-width:660px; padding:0 30px");
    insert_node.appendChild( iframe_doc.createElement("pre") );
    insert_node.lastChild.setAttribute("style", "white-space:pre");
    insert_node.lastChild.appendChild( iframe_doc.createElement("br") );
    range.insertNode( insert_node );

    range.setEndBefore( insert_node ); // カーソルをpre枠の中に入れる
    range.collapse(); // フォーカスを失わないでrangeを閉じる

 

太字の部分は、挿入する「Node」を用意するコードです。 親ノード「div」、その中に子ノードの「pre」更に、その中に子ノードの「br」を作り、それぞれに「style」をセットしています。

 

それらを最終的に「range.insertNode(insert_node);」メソッドで埋め込み、最後にカーソル位置を調整して「range」を閉じます。

 

 

rangeによるカーソル位置のコントロール

上記コードの最後の2行はカーソル位置を調整するものですが、実は問題があります。最後の「range.collapse()」メソッドで「range」を閉じ、カーソルが「pre」枠内に表示されます。 しかし、これに何かをペーストすると、必ず「pre」枠の外にペーストされてしまうのです。

 

 

「→」キーを押し「pre」枠外にカーソルを移動し、再び「←」でカーソルを入れると「pre」枠内にペーストが可能になります。

 

 

他にも「手作業」による操作等があるとペースト可能になりますが、最初の妙な挙動は改善が出来ません。

 

 

rangeを正しく移動して閉じることで解決

これは range操作の間違いが原因でした。「range.insertNode(insert_node);」で「div」「pre」ブロックを埋め込んだ後は、 rangeは「div」の「insert_node」に始点と終点があります。

 

 

この「insert_node」を足場とした「range.setEndBefore(insert_node);」等のメソッドで可能な range操作(上図の赤文字)は、どの場合も「insert_node」の外側を始点や終点としたrangeを指定することになります。

 

私は range操作に未熟で、この赤文字の操作に拘泥していたのが問題でした。

 

 

rangeを移動するには

カーソルを「insert_node」の内部の「pre」に確実に入れるには、「pre」を rangeの始点にして、そこでrangeを閉じる必要があります。 そして rangeの移動には「setStart(足場ノード,n)」「.setEnd(足場ノード,n)」のメソッドが要ります。 

 

そこで、先ず考える range移動のコードは、以下です。

 

range.setStart( insert_node.lastChild, 0 ); // 生成したpreにrange始点を移動

 

「insert_node.lastChild」は「pre」で、これを足場にしてオフセット「0」の位置は「pre」の子要素の最初の位置になります。

 

 

しかし、これで「range.collapse();」を実行すると、またカーソルが「pre」枠の外に出てしまいます。

 

原因は「range.collapse()」が rangeの終点側に閉じるからです。 これで判る事は、range操作はずっと継続していて、「range.insertNode(insert_node);」実行時の range終端が、それ以降も残っているという事です。 rangeの始点側に閉じるには「range.collapse(true);」とすれば良く、これでようやくペースト可能なカーソル配置が出来ました。 以下がカーソル位置操作を修正したコードです。

 

range.setStart( insert_node.lastChild, 0 ); // 生成したpreにrange始点を移動
range.collapse(true); // rangeを始点で閉じる

 

また「.setEnd(足場ノード,n)」を使えば「collapse();」のままでコードが書けます。

 

range.setEnd( insert_node.lastChild, 0 ); // 生成したpreにrange終点を移動
range.collapse(); // rangeを終点で閉じる

 

これも、目的の通りにカーソル位置でペーストが出来ます。

 

なお、「rangeを移動する」には、移動先の足場が必要になりますが、簡単には

 ▪ 親ノードを「parentNode」プロパティ参照で取得する

 ▪ 子ノードを「firstChild」「lastChild」などのプロパティ参照で取得する

というのが、手っ取り早いでしょう。 どうしても適当な足場が無ければ、まわりくどくなりますが、スクリプトで周囲の要素にID属性を付与して移動する手もあります。

 

 

 

自動記入のスクリプトを統合する

Font Awesome ICON 2 」で、編集画面のスクリプトツールのショートカットキー統合の準備が出来ていたので、このページの「pre」枠自動記入のスクリプトに、「Pause」→「F2」のショートカットキーを割り当てました。 今後、「編集画面における自動記入」のツールを統合するので、スクリプト名を「Elements Palette」に改めています。

 

以下のスクリプトは Chrome /  Firefox の「Tampermonkey」で動作を確認しています。

 

〔追記〕2019.05.20

2段階入力の判定部のコードを投稿当初のものから修正しています。

 

〔 Elements Palette 〕 ver. 0.4

// ==UserScript==
// @name         Elements Palette
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  編集枠に各種要素を自動記入するツール
// @author       Ameba Blog User
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @grant        none
// ==/UserScript==

window.addEventListener( 'load', function() {
    'use strict';

var target = document.getElementById('cke_1_contents'); // 監視 target
var monitor = new MutationObserver( catch_key );
monitor.observe(target, {childList: true}); // ショートカット待受け開始

catch_key();


function catch_key() {
var editor_iframe = document.querySelector('.cke_wysiwyg_frame');
var iframe_doc = editor_iframe.contentWindow.document;

iframe_doc.addEventListener( "keydown", check_key );
var gate;
function check_key(event) {
    var send = -1;

    if (event.which == 19 || event.keyCode == 19) { gate = 1; }
    if (event.which == 112 || event.keyCode == 112) {
        if( gate == 1 ){ event.preventDefault(); send = 112; } }
    if (event.which == 113 || event.keyCode == 113) {
        if( gate == 1 ){ event.preventDefault(); send = 113; } }
    if (event.which == 116 || event.keyCode == 116) {
        if( gate == 1 ){ event.preventDefault(); send = 116; } }
    if (event.which != 19 || event.keyCode != 19) { gate = -1; }

    if(send != -1) {
        event.stopImmediatePropagation();
        set_mark(send); }

} // check_key
} // catch_key


function set_mark(sender) {

if( sender == 112) {
    var editor_iframe = document.querySelector('.cke_wysiwyg_frame');
    var iframe_doc = editor_iframe.contentWindow.document;
    var selection = iframe_doc.getSelection();
    var range = selection.getRangeAt(0);
    var insert_node = iframe_doc.createElement("i");
    insert_node.appendChild( iframe_doc.createTextNode("\u00A0") );
    insert_node.setAttribute("class", "fas fa-external-link-alt fa-sm");
    insert_node.setAttribute("style", "margin-left: .5em");
    range.insertNode( insert_node );

    var insert_node_z = iframe_doc.createTextNode("\u200B");
    insert_node.parentNode.insertBefore( insert_node_z, insert_node.nextSibling );
    range.setEnd( insert_node_z.nextSibling, 0 );
    range.collapse(); // フォーカスを失わないでrangeを閉じる
 }

if( sender == 113) {
    editor_iframe = document.querySelector('.cke_wysiwyg_frame');
    iframe_doc = editor_iframe.contentWindow.document;
    selection = iframe_doc.getSelection();
    range = selection.getRangeAt(0);
    insert_node = iframe_doc.createElement("div");
    insert_node.setAttribute("style", "background:#fafafa; border:1px solid #aaa;overflow-y:hidden; max-width:660px; padding:0 30px");
    insert_node.appendChild( iframe_doc.createElement("pre") );
    insert_node.lastChild.setAttribute("style", "white-space:pre");
    insert_node.lastChild.appendChild( iframe_doc.createElement("br") );
    range.insertNode( insert_node );

    range.setEnd( insert_node.lastChild, 0 ); // 生成したpreにrange終点を移動
    range.collapse(); // rangeを始点で閉じる
}

if( sender == 116) {
    alert("F5はショートカットが無効です"); }

} // set_mark
})

 

●「Pause」→「F1」の順にキーを押すと、Font Awesome の「 」アイコンのコードを自動記入します。 但し、ブログページで Font Awesome のアイコンを表示するには「@import」指定が必要です。( 参照ページ 

 

●「Pause」→「F2」の順にキーを押すと、コード掲載用の「pre」枠を自動記入します。 HTMLコードは「通常表示」の編集枠で「pre」枠内にペーストします。 また、CSSコード 、JavaScriptコード は「HTML表示」の編集枠でペーストする方が、好結果です。(ブログページの表示は同じですが、HTML表示が見易くなります)

 

● 長いコードを掲載する場合、以下のコードで縦スクロールバーが表示される縦幅固定の「pre」枠を表示できます。(上記のコード中の太字部を以下に置き換えます)

 

insert_node.setAttribute("style", "background:#fafafa; border:1px solid #aaa;overflow:auto;height:50vh;max-width:660px;padding:0 30px");

 

●「pre」枠内で改行しようと「Enter」キーを押すと、表面上は判り難いが HTML上で「pre」ブロックが分裂して生成されます。「通常表示」からは行間隔が間延びして初めて気付きます。「pre」枠内で改行する場合は「Shift + Enter」を押します。

 

 

 

「Elements Palette ⭐」最新版について 

旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。

 

●「Elements Palette ⭐」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。