「BR Checker」の機能
通常の空白行は「Enter」キーを押し <p> </p>のコードが生成されますが、編集過程で <br>が生成された状態で同様に見える場合があります。「BR Checker」は、記事中の <br>タグの位置を「▼」のマークで示します。 更に「To Space」は、自動的に <br>を置き換えて、編集機能の標準の<p>タグを使った形に整形します。
また「BR Checker」が起動中に、文書中の「pre枠」を右クリックすると、枠内の「 」を「半角空白」に書き換えると同時に、編集自動機能でリンクが付帯した文字列からリンクコードのみを削除する事ができます。 これは「pre枠」に対する整形機能です。
以上が、総合的な文書整形ツール「BR Checker + To Space ⭐」の機能ですが、前ページの文字数カウンターを、これに組み込む事にしました。
書式整形ツールと編集文字数カウンターは、記事編集の最終段階で使用する事が多く、「 」処理は文字数を減らす機能です。 そのため、カウンターの併合は合理的ですが、ショートカットの節約の意味もあります。
文字数カウンターの組込み
下は、デフォルトの「文字数」表示です。
「BR Checker + To Space ⭐」の操作は「Ctrl + F9」「Ctrl + F10」の2つのショートカットで行いますが、これが押された場合にカウンターが働いて、デフォルトの「文字数」表示に、このツールのカウンター値を追加する様にしました。
このツールのカウンターは、自動的には更新されず「Ctrl + F9」「Ctrl + F10」を押した時にだけカウント値を更新します。
◎「BR Checker」をONにする場合もOFFにする場合も、チェッカーが動作します。
◎ アメブロの記事の文字数制限は、記事本文のHTMLソースの半角換算で約40000字とされていますが、このカウンターでは、約38000~40000文字が上限になります。
「BR Checker + To Space (nbsp) ⭐」ver. 2.0
◎このツールは Chrome / 新Edge / Firefox の拡張機能「Tampermonkey」上で動作を確認しています。「Tampermonkey」の導入と初期設定などについては、以下を参照ください。
◎以下のコードを「Tampermonkey」の新規作成画面にコピー&ペーストして保存すれば、最新版エディタの「編集画面」でこのツールを使用する事が出来ます。 また、以前のバージョンをインストールしている場合は、OFFにするか「Tampermonkey」から削除して、同時にONにする事は避けてください。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
〔 BR Checker + To Space (nbsp) ⭐ 〕 ver. 2.0
// ==UserScript==
// @name BR Checker + To Space (nbsp) ⭐
// @namespace http://tampermonkey.net/
// @version 2.0
// @description Blogの書式整形ツール・文字数カウンター 統合版
// @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 marked1=0; // BR Checker 起動・非起動の指標
let marked2=0; // To Space (nbsp) 起動・非起動の指標
let target;
let editor_iframe;
let iframe_doc;
let iframe_body;
let pre_box; // PRE枠のコンテナブロック
let css=[
'.brm { position: absolute }',
'i.brm:before { content: "▼"; color: red; margin-left: -2px; font-style: normal }',
'p.brs:before { content: "▼"; color: #008fff; margin-left: -2px; font-style: normal }',
'.disp_line { display: inline-block; margin: 0 0 4px 8px; padding: 4px 15px 1px;',
'font-size: 16px; color: #fff; background: red }'].join(' ');
target=document.getElementById('cke_1_contents'); // 監視 target
let monitor=new MutationObserver(catch_key);
monitor.observe(target, {childList: true}); // ショートカット待受け開始
catch_key();
function catch_key(){
if(document.querySelector('.l-gHeaderLeft__link a')){ // 起動を「トップページ」アイコンに表示 📛
document.querySelector('.l-gHeaderLeft__link a').style.boxShadow='inset -14px 0 0 0 #79fbf6'; }
let send;
editor_iframe=document.querySelector('.cke_wysiwyg_frame');
if(editor_iframe){ // WYSIWYG表示が実行条件
iframe_doc=editor_iframe.contentWindow.document;
if(marked1==1){
sign(); }
if(marked2==1){
active(); }
document.addEventListener("keydown", check_key);
iframe_doc.addEventListener("keydown", check_key);
function check_key(event){
let gate=-1;
if(event.ctrlKey==true){
if(event.keyCode==120){
event.preventDefault(); send=120; gate=1; }} // ショートカット「Ctrl+F9」
if(event.ctrlKey==true){
if(event.keyCode==121){
event.preventDefault(); send=121; gate=1; }} // ショートカット「Ctrl+F10」
if(editor_iframe){
if(gate==1){
event.stopImmediatePropagation();
event.preventDefault();
set_task(send); }}}
brfore_end(); }} // catch_key
function set_task(send){
counter();
if(send==120){ //「Ctrl+F9」 BR Checker / To Space (nbsp) スイッチ
if(marked1==0){
marked1=1;
marked2=1;
sign();
active(); } // BR Checker / To Space (nbsp) をON
else if(marked1==1){
marked1=0;
marked2=0;
sign_clear();
disable(); }} // BR Checker / To Space (nbsp) をOFF
if(send==121){ //「Ctrl+F10」BR Rewrite スイッチ
marked1=1;
sign_clear();
rewrite(); }
} // set_task
// ********** BR Rewrite Functions **************
function rewrite(){
let br_tag;
let br_rewrite;
let o_tag;
let native_line;
first_rw(go_back);
function first_rw(){
let wysiwyg=iframe_doc.querySelector('html');
native_line=wysiwyg.scrollTop; // 通常表示のスクロール位置を記録
br_tag=iframe_doc.querySelectorAll('br');
for(let i=0; i < br_tag.length; i++){
if(br_tag[i].parentNode.tagName=="P" && br_tag[i].parentNode.childNodes.length !=1){
br_rewrite=iframe_doc.createElement("p");
br_rewrite.appendChild(iframe_doc.createTextNode(""));
br_rewrite.setAttribute("class", "brs");
br_tag[i].parentNode.replaceChild(br_rewrite, br_tag[i]); }}
go_back(); }
function go_back(){
document.querySelector('button[data-mode="source"]').click(); // HTML表示に移動
let interval0=setInterval(find_mirror, 10);
function find_mirror(){
let CodeMirror=document.querySelector('.CodeMirror');
if(CodeMirror){
clearInterval(interval0);
document.querySelector('button[data-mode="wysiwyg"]').click();
go_back2(); }}}
function go_back2(){
let interval1=setInterval(find_iframe, 10);
function find_iframe(){
let editor_iframe=document.querySelector('.cke_wysiwyg_frame');
if(editor_iframe){
iframe_doc=editor_iframe.contentWindow.document;
if(iframe_doc){
clearInterval(interval1);
setTimeout( function(){
second_rw(); }, 400);
setTimeout( function(){
sign(); }, 800); }}}}
function second_rw(){
o_tag=iframe_doc.querySelectorAll('.brs');
if(o_tag.length >0){
for(let i=0; i < o_tag.length; i++){
if(o_tag[i].nextElementSibling==o_tag[i+1] ){
o_tag[i].classList.remove('brs'); } // 2連 .brs 生成の場合は先頭側class名を削除
else{
o_tag[i].remove(); }}} // 単体の .brs の場合は削除(上の後方側も含む)
let wysiwyg=iframe_doc.querySelector('html');
wysiwyg.scrollTop=native_line; }} // 記録された通常表示のスクロール位置に移動
// ********** BR Checker Functions **************
function sign(){
let br_tag;
let br_mark;
let i_tag;
let o_tag;
let c_br=0;
let c_br_span;
let c_brrw=0;
let c_brrw_span;
let disp;
let style_inn=iframe_doc.createElement('style'); // iframe内の BRのデザインを指定
style_inn.setAttribute("id", "style_inn");
style_inn.insertAdjacentHTML('afterbegin', css);
let html=iframe_doc.getElementsByTagName('html')[0];
if(!html.querySelector('#style_inn')){
html.appendChild(style_inn); }
i_tag=iframe_doc.querySelectorAll('.brm');
if(i_tag.length >0){
for(let i=0; i < i_tag.length; i++){ i_tag[i].remove(); }} // BRマーク削除してリセット
o_tag=iframe_doc.querySelectorAll('.brs'); // 処理時の brshell の処理残りをカウント確認
if(o_tag.length >0){
c_brrw=o_tag.length; }
else{ c_brrw=0; }
br_tag=iframe_doc.querySelectorAll('br');
for(let i=0; i < br_tag.length; i++){
if(br_tag[i].parentNode.tagName=="P" &&
br_tag[i].parentNode.childNodes.length !=1){
c_br +=1;
br_mark=iframe_doc.createElement("i");
br_mark.appendChild(iframe_doc.createTextNode("")); // 空白文字
br_mark.setAttribute("class", "brm");
br_tag[i].parentNode.insertBefore(br_mark, br_tag[i]); }
else{ continue; }} // BRマーク表示
disp=document.createElement("span");
disp.setAttribute("class", "disp_line");
disp.appendChild(document.createTextNode("▼ BR Checker count : "));
c_br_span=document.createElement("span");
c_br_span.setAttribute("style", "font-weight: bold");
c_br_span.appendChild(document.createTextNode(c_br));
disp.appendChild(c_br_span);
disp.appendChild(document.createTextNode(" / shell:"));
c_brrw_span=document.createElement("span");
c_brrw_span.setAttribute("style", "font-weight: bold");
c_brrw_span.appendChild(document.createTextNode(c_brrw));
disp.appendChild(c_brrw_span);
if(marked2==1){
disp.appendChild(document.createTextNode(" ■ To Space (nbsp) ")); }
monitor.disconnect(); // MutationObserverを BR Checker 起動表示に反応させない
let style_ext=document.createElement('style'); // disp_line のデザインを指定
style_ext.setAttribute("id", "style_ext");
style_ext.insertAdjacentHTML('afterbegin', css);
if(!target.querySelector('#style_ext')){
target.appendChild(style_ext); }
if(target.querySelector('.disp_line')){
target.querySelector('.disp_line').remove();
target.insertBefore(disp, editor_iframe); }
else{
target.insertBefore(disp, editor_iframe); }
monitor.observe(target, {childList: true}); } // BR Checker 起動表示
function sign_clear(){
let i_tag;
editor_iframe=document.querySelector('.cke_wysiwyg_frame');
iframe_doc=editor_iframe.contentWindow.document;
if(target.querySelector('.disp_line')){
target.querySelector('.disp_line').remove(); } // BR Checker 起動表示を削除
i_tag=iframe_doc.querySelectorAll('.brm');
if(i_tag.length >0){
for(let i=0; i < i_tag.length; i++){ i_tag[i].remove(); }}} // BRマーク削除
// ********** To Space (nbsp) Functions **************
function active(){
let buffer;
let nbsp;
let a_count;
iframe_doc=editor_iframe.contentWindow.document;
if(iframe_doc){ //「通常表示」が動作条件
iframe_body=iframe_doc.querySelector('body.cke_editable');
pre_box=iframe_body.querySelectorAll('div');
buffer=Array(pre_box.length);
for(let i=0; i<pre_box.length; i++){
select_pre_box(i); }
function select_pre_box(i){
pre_box[i].oncontextmenu=function(){
if(pre_box[i].firstChild.tagName=='PRE'){
select_box(select_do);
return false;
function select_box(select_do){
boxshadow();
setTimeout( select_do, 100); }
function boxshadow(){
pre_box[i].style.outline='2px solid #03a9f4'; }
function select_do(){ start_select(i); }}}}
function start_select(i){
let regex=new RegExp('\u00A0', 'g');
let nbsp=pre_box[i].innerText.match(regex);
let pa_count=pre_box[i].getElementsByTagName("a");
if(buffer[i] !=null){
let ok=confirm(" ❎ 変換前に戻しますか?");
if(ok){
pre_box[i].firstChild.innerHTML=buffer[i];
buffer[i]=null;
pre_box[i].style.outline='none'; }}
else{
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){ to_space(i); }
else{ pre_box[i].style.outline='none'; }}
else{ ; }}}
function to_space(i){
a_count=0;
buffer[i]=pre_box[i].firstChild.innerHTML; // 選択pre枠のデータバックアップ
let child_node=pre_box[i].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){
pre_box[i].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=pre_box[i].innerText.match(regex);
if(nbsp !=null){
alert("❌ 変換できなかった「 」の数 : " + nbsp.length );}
if(a_count !=0){
alert("❌ 置換えが出来ない「a要素」 : " + a_count); }}}}
function disable(){
for(let i=0; i<pre_box.length; i++){
if(pre_box[i].firstChild.tagName=='PRE'){
pre_box[i].style.outline='none'; }} // 処理済枠の outline を削除
pre_box=[]; }// 動作の無効化
// ********** Before End Functions **************
function brfore_end(){
var submitButton=document.querySelectorAll('.js-submitButton');
if(editor_iframe !=null){ //「通常表示」編集画面が実行条件
submitButton[0].addEventListener("mousedown", all_clear, false);
submitButton[1].addEventListener("mousedown", all_clear, false);
submitButton[2].addEventListener("mousedown", all_clear, false); }
function all_clear(){
let o_tag=iframe_doc.querySelectorAll('.brs'); // 処理時の brshell の処理残りをカウント確認
if(o_tag.length >0){
alert("⛔ BR削除処理が不完全です BR-Shell数:" + o_tag.length +"\n\n" +
" BR削除「Ctrl + F10」 を再実行してください");
event.stopImmediatePropagation();
event.preventDefault(); }
else{
let i_tag;
editor_iframe=document.querySelector('.cke_wysiwyg_frame');
iframe_doc=editor_iframe.contentWindow.document;
i_tag=iframe_doc.querySelectorAll('.brm');
if(i_tag.length >=1){
for(let i=0; i < i_tag.length; i++){ i_tag[i].remove(); }} // マーク削除
let pre_box;
iframe_body=iframe_doc.querySelector('body.cke_editable');
pre_box=iframe_body.querySelectorAll('div');
for(let i=0; i<pre_box.length; i++){
if(pre_box[i].firstChild.tagName=='PRE'){
pre_box[i].style.outline='none'; }}}}}// 処理済枠の outline を削除
// ********** Editor Counter **************
function counter(){
let html_source;
let count_display;
let chr_count;
iframe_doc=editor_iframe.contentWindow.document;
if(iframe_doc){ //「通常表示」が動作条件
iframe_body=iframe_doc.querySelector('.cke_editable');
html_source=iframe_body.innerHTML; // HTMLソースコードを取得
chr_count=get_count(html_source);
let wordcount=document.querySelector('.cke_wordcount');
wordcount.style.margin="9px 20px 0 0";
wordcount.style.padding="0 10px";
let path_item=document.querySelector('.cke_path_item');
path_item.style.font="normal 14px Meiryo";
path_item.style.color="#000";
let real_count=document.createElement("span");
real_count.setAttribute("class", "real_count");
real_count.style.font="normal 14px Meiryo";
real_count.style.color="#000";
if(wordcount.querySelector('.real_count')){
wordcount.querySelector('.real_count').remove(); }
wordcount.appendChild(real_count);
real_count.innerHTML=' 半角: ' + chr_count;
function get_count(str){
let result=0;
for(let i=0; i<str.length; i++){
let chr=str.charCodeAt(i);
if((chr>=0x00 && chr<0x81) || (chr===0xf8f0) ||
(chr>=0xff61 && chr<0xffa0) || (chr>=0xf8f1 && chr<0xf8f4)){
result += 1; } //半角文字の場合は1を加算
else{
result += 2; }} //それ以外の文字の場合は2を加算
return result; }}}
} // main()
「BR Checker」「To Space (nbsp)」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「BR Checker」は、後に「BR Checker+Outro Style ⭐」に統合されています。 その最新バージョンへのリンクは、以下のページのリンクリストから探せます。
●「To Space (nbsp)」は、後に「PreBox Tools ⭐」に統合されています。 その最新バージョンへのリンクは、以下のページのリンクリストから探せます。



