「PreBox Tools ⭐」とは
「PreBox Tools ⭐」は、編集画面に配置した「コード表示枠」(pre枠)を扱う上で、必要な機能を統合したツールです。 この「pre枠」をアメーバブログで利用する方はそう多くないと思いますが、これはプログラムコードを掲載する際に必要です。
◎ プログラムコードである事を、一目で判り易く読者に表示する
◎ コードのインデントが正しく表示され、コード内容が判読し易い
◎ コードのコピーが可能で、コードテストやプログラムの利用が簡単にできる
◎ テキスト検索で、コード上の文字列も検索範囲に入る
といった要件は「pre枠」を使うことで、比較的簡単に可能になります。 ネット上でコードを掲載するページで、「pre枠」はとても多く使われています。
実際、このツールを必要とする方は稀と思いますが、ブログの可能性を拡張し、より有意義な場に高めるため、こういったツールの公開は決して無駄ではないでしょう。 他のブログでも、コードの移植・利用が可能な場合は多いですから。
今回の更新内容
このツールは2020年に制作し、幾つかのツールの分散・統合して、現在の形になりました。 その際、コーディングの未熟さから、マウス操作の選択肢が少なく、これまでのバージョンは、使える操作の中で選択した操作方法を不本意に利用していました。
「pre枠」をマウスでクリックする際に、「Ctrl」「Shift」「Alt」を同時押しする事で、機能を選択していますが、「右Click」「左Click」と組み合わせると、6通りの選択肢があるはずです。
ところが、実際に動かない組み合わせがありました。 今回、慣れた目でコードを見直すと、「Ctrl」「Shift」「Alt」の選択分岐を、2ヵ所で別々に書いていたので、この問題が生じている事に気付きました。 複数のツールを統合する際に、ありがちな事かも知れません。
これを1箇所で選択する様に、コードを書き直しました。 かなりの書換えで、変数、関数の整理などを経て、とても見通しの良いコードになりました。 一歩前進です。 そして、マウスによる機能選択が自由な組み合わせで可能になったので、これを一新しました。
「PreBox Tools ⭐」の仕様と操作方法
●「通常表示」の編集画面で、「Ctrl+F7」を押すと下の「表示パネル」が出ます。 これはスイッチではなく単なる起動表示で、マウス操作をここに表示しています。
● この状態で、ツールの各機能が利用できます。「Ctrl+F7」をもう一度押すと「表示パネル」が消え、このツールが終了します。
このツールは3つの機能があります。 以下はその機能とそれを指定する操作です。
起動する機能 | 機能を指定する操作 |
To Space (nbsp) + zw_space |
コード枠を 「Ctrl+左Click」 |
Code Copy | コード枠を 「Ctrl+右Click」 |
Scroll Fix | コード枠を 「Alt+左Click」 |
To Space (nbsp)
●「pre枠」を「Ctrl+左Click」すると、コード内の「 」を「半角スペース」に変更する機能が起動します。
▪「 」は編集枠へのペースト時に大量に書き込まれ、文字数を増やします。
▪ コード上のリンク文字列は「a要素」と誤解釈され、コピーされたコードを無効にする場合があるので、これを単なる文字列に戻します。
●「OK」を押すと「pre枠」内のコードの整形処理が実行されます。
▪ 処理後の「pre枠」にはブルー枠が表示されます。
▪ 処理済の「pre枠」を「右クリック」すると処理をアンドゥできます。
▪ ブルー枠は、「Ctrl+F7」でツールを終了すると自動的に消えます。
●「To Space (nbsp)」のコード整形処理に続いて、自動的に特殊文字「\u200B」の混入をチェックします。 もしこの文字を発見した場合は、削除を確認するダイアログが表示されます。 このチェック機能は ver. 1.4 より追加しました。
Code Copy
●「pre枠」を「Ctrl+右Click」すると、「pre枠」内のコードを全選択します。
▪「pre枠」内のコードだけを全コピーしたり、全削除する場合に利用します。
Scroll Fix
●「pre枠」を「Alt+左クリック」すると、スクロール表示の「pre枠」を非スクロール表示に変更します。 これは一時的な変更で「pre枠」にグリーン枠を表示します。
▪コードの検索/置換では、全コードが見える非スクロール表示が必要になります。
● 変更した「pre枠」は「Alt+左クリック」で元に戻ります。 また、これはツールによる仮表示で、「Ctrl+F7」でツールを終了した場合は、自動的に元に戻ります。
ヘルプボタン
ヘルブボタンを設置しました。 これは、このページを表示します。
操作上の注意点
起動のショートカット
ブラウザの「カーソルブラウジング」が「F7」キーに設定されている事により、このツールを起動する「Ctrl+F7」が効かない場合があります。 回避方法は、以下のいずれかの方法を試してください。
◎「Ctrl+Shift+F7」を押す。
◎ 漢字変換をOFFにしてから「Ctrl+F7」を押す。
◎ 編集枠余白部をクリックして、編集枠外にフォーカスを移し「Ctrl+F7」を押す。
「通常表示」⇄「HTML表示」の移動
このツールを起動中で(パネルが表示)、 「To Space (nbsp)」処理後のブルー枠、 「Scroll Fix」のグリーン枠と拡張した「pre枠」などが表示された状態であっても、「HTML表示」を開くことに問題はありません。(特に「To Space 」の実際の動作は「HTML表示」を見ると良く判ります。) 元の「通常表示」に戻ると、「HTML表示」に移動した時の状態が再現されます。
「Ctrl+F7」でツールを終了すると、ブルー枠やグリーン枠は消え、記事の本来の表示になります。 非スクロール表示のグリーン枠の状態で「下書き保存」「投稿する」をした場合は、ボタンを押した瞬間に本来の表示に戻って保存されます。
なお、「HTML表示」の編集画面で「下書き保存」「投稿する」を押した場合は、ツールの枠線の除去が出来ないので、通常表示で終了する様に説明が出ます。
もとに戻す操作
長期にわたり使用して来ましたが、「To Space (nbsp)」によるコードデータの損失は一度も経験がありません。 制作の初期は判らなかったので、「pre枠」内のデータをバックアップし、処理後に問題があれば元に戻す(アンドゥ)機能を実装しています。 これは余り使う事はないと思いますが、正常に使えます。
ただし、このバックアップは、ツールを「Ctrl+F7」で起動して、終了をするまでの間の保持だけで、「Ctrl+F7」で終了した時点でリセットされます。 編集画面を閉じてもう一度開いた所から、アンドゥで前の画面の状態に戻せないのと同じです。
「PreBox Tools ⭐」を利用するには
このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。
❶「Tampermonkey」を導入します
◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。
既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。
拡張機能の導入については、以下のページに簡単な説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
◎「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
〔 PreBox Tools ⭐ 〕 ver. 1.3
// ==UserScript== // @name PreBox Tools ⭐ // @namespace http://tampermonkey.net/ // @version 1.3 // @description 「pre枠」関連総合編集ツール 「Ctrl+F7」 // @author Ameba Blog User // @match https://blog.ameba.jp/ucs/entry/srventry* // @exclude https://blog.ameba.jp/ucs/entry/srventrylist.do* // @grant none // ==/UserScript== let retry=0; let interval=setInterval(wait_target, 100); function wait_target(){ retry++; if(retry>10){ // リトライ制限 10回 1sec clearInterval(interval); } let target=document.getElementById('cke_1_contents'); // 監視 target if(target){ clearInterval(interval); main(); }} function main(){ let mode=0; let box_mode=0; // boxの状態 let box_i; // boxの選択 let editor_iframe; let iframe_doc; let iframe_body; let wysiwyg; // 通常表示の iframe内 html let buffer=[]; // box内データのバックアップ用配列 let target=document.getElementById('cke_1_contents'); // 監視 target let monitor=new MutationObserver(catch_key); monitor.observe(target, {childList: true}); // ショートカット待受け開始 catch_key(); function catch_key(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; when_back(); right_select(); document.addEventListener('keydown', check_key); // iframe外 iframe_doc.addEventListener('keydown', check_key); // iframe内 function check_key(event){ if(event.ctrlKey && event.keyCode==118){ // ショートカット「Crtl+F7」 event.preventDefault(); event.stopImmediatePropagation(); if(mode==0){ mode=1; sign(); right_select(); box_act(); } else if(mode==1){ mode=0; buffer=[]; // ツールOFF時にバッファークリア 🔵 sign_clear(); tospace_clear(); box_close(); }}}} before_end(); } // catch_key() function when_back(){ // HTML表示から戻った時に処理状態を再現表示 editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ if(mode==1){ sign(); box_act(); }}}} // ********** Menu Display and additional function ************** function sign(){ monitor.disconnect(); // 起動時セットアップを MutationObserverに反応させない editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; let style_sbf= '<style id="style_sbf">'+ '.open_box { outline: 2px solid #009688 !important; height: auto !important; } '+ '.clean_box { outline: 2px solid #03a9f4 !important; }'+ '</style>'; if(!iframe_doc.documentElement.querySelector('#style_sbf')){ iframe_doc.documentElement.insertAdjacentHTML('beforeend', style_sbf); }} let SVG_h= '<svg id="help_pbt" viewBox="0 0 150 150">'+ '<path fill="#fff" d="M66 13C56 15 47 18 39 24C-12 60 18 146 82 137C92 '+ '135 102 131 110 126C162 90 128 4 66 13M68 25C131 17 145 117 81 '+ '125C16 133 3 34 68 25M69 40C61 41 39 58 58 61C66 63 73 47 82 57C84 '+ '60 83 62 81 65C77 70 52 90 76 89C82 89 82 84 86 81C92 76 98 74 100 66'+ 'C105 48 84 37 69 40M70 94C58 99 66 118 78 112C90 107 82 89 70 94z">'+ '</path></svg>'; let disp_sf= '<div id="disp_sf">'+ SVG_h+' '+ '■ To Space (nbsp): Ctrl+L-Click ■ Code Copy: Ctrl+R-Click ■ Scroll Fix: Alt+Click'+ '</div>'+ '<style>'+ '#cke_1_contents { display: flex; flex-direction: column; } '+ '#disp_sf { position: relative; margin: 0 0 5px; padding: 4px 0 1px; '+ 'font: 16px/24px Meiryo; color: #fff; background: #009688; white-space: nowrap; } '+ '#help_pbt { position: absolute; top: 7px; left: 6px; height: 16px; width: 16px; '+ 'cursor: pointer; }'+ '</style>'; editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ if(!document.querySelector('#disp_sf')){ editor_iframe.insertAdjacentHTML('beforebegin', disp_sf); }} monitor.observe(target, {childList: true}); document.querySelector('#disp_sf').style.display='block'; let help=document.querySelector('#help_pbt'); help.onclick=function(){ window.open("https://ameblo.jp/personwritep/entry-12760312656.html", '_blank'); } } // sign() function sign_clear(){ if(target.querySelector('#disp_sf')){ target.querySelector('#disp_sf').style.display='none'; }} // 起動表示を非表示 // *********** Pre Box Right Select ******************** function right_select(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ let iframe_body=iframe_doc.querySelector('body'); if(iframe_body){ let target_pre=iframe_body.querySelectorAll('pre'); for(let i=0; i<target_pre.length; i++){ target_pre[i].oncontextmenu=function(event){ if(event.ctrlKey){ event.preventDefault(); event.stopImmediatePropagation(); select_code(target_pre[i]); }}} function select_code(box){ let selection=iframe_doc.getSelection(); let range=iframe_doc.createRange(); range.selectNodeContents(box); selection.removeAllRanges(); selection.addRange(range); } }}}} // right_select() // ********** Scroll Fix & To Space (nbsp) ************** function box_act(){ let pre_box; // PRE枠のコンテナブロック editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ iframe_body=iframe_doc.querySelector('body'); if(iframe_body){ pre_box=iframe_body.querySelectorAll('div'); for(let i=0; i<pre_box.length; i++){ pre_box[i].onclick=function(event){ if(event.altKey){ event.preventDefault(); event.stopImmediatePropagation(); scroll_fix(pre_box[i], i); } if(event.ctrlKey){ event.preventDefault(); event.stopImmediatePropagation(); edit_box(pre_box[i], i); }}} function scroll_fix(box, index){ if(box_mode==0 && mode==1){ box_mode=1; // boxのScroll設定を外す let style_set=window.getComputedStyle(box, null); if(style_set.getPropertyValue('overflow')){ if(style_set.getPropertyValue('overflow')=='scroll' || style_set.getPropertyValue('overflow')=='auto' || style_set.getPropertyValue('overflow')=='overlay'){ box_i=index; box.classList.add('open_box'); }} else if(style_set.getPropertyValue('overflow-y')){ if(style_set.getPropertyValue('overflow-y')=='scroll' || style_set.getPropertyValue('overflow-y')=='auto' || style_set.getPropertyValue('overflow-y')=='overlay'){ box_i=index; box.classList.add('open_box'); }}} else{ if(index==box_i){ box_mode=0; // boxのScroll設定を元に戻す box.classList.remove('open_box'); }} } // scroll_fix() function edit_box(box, index){ let nbsp; let a_count; if(box.firstChild.tagName=='PRE' && mode==1){ let regex=new RegExp('\u00A0', 'g'); let nbsp=box.innerText.match(regex); let pa_count=box.getElementsByTagName("a"); if(!box.classList.contains('clean_box')){ if(nbsp !=null || pa_count.length !=0){ let ok; if(nbsp==null && pa_count.length !=0){ ok=confirm(" ⏬ 「 」 0 個\n"+ " 「a要素」 " + pa_count.length + " 個をテキストに置換えます"); } else if(nbsp !=null && pa_count.length==0){ ok=confirm(" ⏬ 「 」 " + nbsp.length + " 個を半角空白に変換します\n"+ " 「a要素」 0 個"); } else{ ok=confirm(" ⏬ 「 」 " + nbsp.length + " 個を半角空白に変換します\n"+ " 「a要素」 " + pa_count.length + " 個をテキストに置換えます"); } if(ok){ if(buffer[index]==null){ buffer[index]=box.firstChild.innerHTML; } // 選択pre枠のデータバックアップ 🔵 box.classList.add('clean_box'); to_space(box, index); }} else{ box.classList.add('clean_box'); }} else{ let ok=confirm(" ❎ 変換前に戻しますか?"); if(ok){ if(buffer[index]!=null){ box.firstChild.innerHTML=buffer[index]; buffer[index]=null; } // バッファークリア 🔵 box.classList.remove('clean_box'); }}} function to_space(box, index){ a_count=0; let child_node=box.firstChild.childNodes; for(let t=0; t<child_node.length; t++){ if(child_node[t].nodeType==3){ child_node[t].nodeValue=child_node[t].nodeValue.replace(/\u00A0/g , '\u0020'); } else if(child_node[t].nodeType==1 && child_node[t].tagName=="A"){ let inner_node=child_node[t].childNodes; if(inner_node.length==1 && inner_node[0].nodeType==3){ box.firstChild.replaceChild(inner_node[0], child_node[t]); } // text を a要素と入替え else{ a_count +=1; }} // 子ノードが1個の textの条件に当てはまらない a要素 else{ let child_node2=child_node[t].childNodes; if(child_node2){ for(let t2=0; t2<child_node2.length; t2++){ if(child_node2[t2].nodeType==3){ child_node2[t2].nodeValue= child_node2[t2].nodeValue.replace(/\u00A0/g , '\u0020'); } else{ let child_node3=child_node2[t2].childNodes; if(child_node3){ for(let t3=0; t3<child_node3.length; t3++){ if(child_node3[t3].nodeType==3){ child_node3[t3].nodeValue= child_node3[t3].nodeValue.replace(/\u00A0/g , '\u0020'); } }}}}}}} let regex=new RegExp('\u00A0', 'g'); nbsp=box.innerText.match(regex); if(nbsp !=null){ alert("❌ 変換できなかった「 」の数 : " + nbsp.length );} if(a_count !=0){ alert("❌ 置換えが出来ない「a要素」 : " + a_count); } } // to_space() } //edit_box() }}}} // box_act() // ********** Scroll Fix additional function ************** function box_close(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ box_mode=0; let open_box=iframe_body.querySelectorAll('.open_box'); for(let i=0; i<open_box.length; i++){ open_box[i].classList.remove('open_box'); }}}} // 処理枠の outline を削除 // ********** To Space (nbsp) additional function ************** function tospace_clear(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); if(editor_iframe){ iframe_doc=editor_iframe.contentWindow.document; if(iframe_doc){ let clear_box=iframe_doc.querySelectorAll('.clean_box'); for(let i=0; i<clear_box.length; i++){ clear_box[i].classList.remove('clean_box'); }}}} // 処理枠の outline を削除 // ********** Before End ********************************* function before_end(){ editor_iframe=document.querySelector('.cke_wysiwyg_frame'); let submitButton=document.querySelectorAll('.js-submitButton'); submitButton[0].addEventListener("click", all_clear, false); submitButton[1].addEventListener("click", all_clear, false); function all_clear(){ if(!editor_iframe){ //「HTML表示」編集画面の場合 alert("⛔ PreBox Tools ⭐ の終了処理ができません\n\n"+ " 通常表示画面に戻り 編集を終了してください"); event.stopImmediatePropagation(); event.preventDefault(); } if(editor_iframe){ //「通常表示」編集画面の場合 if(mode!=0){ mode=0; box_mode=0; tospace_clear(); box_close(); }} }} // before_end() } // main()
「PreBox Tools ⭐」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「PreBox Tools ⭐」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。