濁点と半濁点の入力間違い 

視力とディスプレイの問題があると思いますが「ブ」「プ」を間違って入力しているのに気付かない場合がたまにあります。 この間違いは、ローマ字入力の人には生じないでしょう。

 

ひらがな入力では、「ふ」を入力して「゛」か「゜」を打って「濁点」「半濁点」を決めます。 この時に「濁点」「半濁点」の記号が隣にあり、指の位置が少しズレると違った方になるわけです。

 

ローマ字入力では「pu /ぷ」「bu /ぶ」はキーが離れていて間違い様がないと思いますが、ローマ字入力でこういうタイプの誤入力の例は他の文字であるのかも?

 

 

 

で、この間違いを生じる文字は「は行」「ハ行」のみで、「日本語の文字」では「ひらかな」「カタカナ」の20文字しかありません。 つまり、「パピプ…」「バビブ…」の 20文字をチェックすれば、「濁点」「半濁点」の間違いはなくせます。

 

ブログ編集画面で「S-R in Editor ⭐」を使えば「パ」と「バ」のチェックは2回の検索で出来ますが、全20文字では20回が必要です。 検索語(文字)は決まっているので、自動的にこの20文字を拾い出す検索ツールを試作して見ました。

 

AIの漢字変換が出来て久しく、自動校正ツールなども世の中にありそうですが、編集画面の中では動作しそうにないので、実用性は作って見てから考える事に..

 

 

 

Dakuten ⭐ 

もちろん最初からツールを作る必要は無く、「S-R in Editor ⭐」を組み変えて2日余りの時間でツールが出来ました。

 

function t_process(){
    let search_word=
        ["ぱ","ぴ","ぷ","ぺ","ぽ","ば","び","ぶ","べ","ぼ","パ","ピ","プ","ペ","ポ","バ","ビ","ブ","ベ","ボ"];
    let rep_word;
    let rep_buffer=buffer;
    for(let k=0; k<search_word.length; k++){
        rep_word='<mu>'+ search_word[k] +'</mu>';
        rep_buffer=rep_buffer.replace(new RegExp(search_word[k], 'g'), rep_word); }

    iframe_body.innerHTML=rep_buffer;
    let mu_all=iframe_body.querySelectorAll('mu');
    count_t=mu_all.length; }

 

上の関数が、20文字を検索するエンジンです。 単純なもので、順番に本文の検索をくり返しているだけです。 検索の1回ごとに、ヒットした文字を「<mu>ぱ</mu>」と言った「muタグ」に書換えて行きます。「muタグ」は実際のHTMLには規定がない「独自仕様」ですが、このツール内ではタグとして機能します。

 

最後に、その「muタグ」のデザインを指定する事で、本文内で検索ヒットした文字をハイライト表示しますが、これも「S-R in Editor ⭐」の踏襲です。

 

 

 編集画面で使える検索/置換えツール

初見の方のために「S-R in Editor ⭐」について少し。 編集画面内でブラウザによる「Ctrl+F」検索は可能ですが、置換えはできません。「S-R in Editor ⭐」はアメーバ編集画面専用の検索置換え機能です。 ヒット文字の記事上でのチェック、一括と点検しながらの置換え、複数記事での同作業の継続などが可能です。

 

 

 

 

「Dakuten ⭐」の操作方法 

起動のショートカットは「F10」のダブル押下にしました。「ダブル押下」は、キーを2回、素早く押下する操作です。 

 

● 編集画面で「F10」をダブル押下すると、記事タイトルの左横に「小パネル」が出ます。

 

 

 

▪「濁点/半濁点」の文字の総数が「Count」として表示されます。

 

▪ 本文中の「濁点/半濁点」の全ての文字に、「オレンジ」の下線が付きます。 

 

▪「⇧」「⇨」「⇩」「⇦」のキーで、順に「濁点/半濁点」の文字が選択されて、選択された文字の下線が「赤下線」になります。 このマークは、チェックしている文字の場所を明示するためのマークです。

 

 

● 再度「F10」をダブル押下すると「小パネル」と「文字のマーク」が消え、ツールが終了します。

 

 

本文チェックと修正 

このツールで「濁点」「半濁点」の入力間違いをチェックします。「⇧」「⇩」キーで順にヒットした文字を含む単語を確認します。 もし間違いを見つけた場合は、その場でキャレットを入れて文字を修正できます。

 

▪ このツールが動作中は、方向キーはキャレットの移動に使えません。 ツールを終了すると、通常の通りキャレット移動に使える様になります。

 

▪ 検索チェック時は、HTML表示を出来ない様に「通常表示」「HTML表示」のボタンが非表示になります。 ツールを終了するとボタンが使える様になります。

 

 

使用上の注意点 

チェック・修正が終わったら、「F10」キーのダブル押下でツールを終了してから記事の保存を行ってください。 ツールの終了をせずに投稿・保存をした場合、ハイライト表示のタグが残らない様に自動的に消去をしますが、システムに絶対はないので。

 

 

 

「Dakuten ⭐」を利用するには

このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。

 

❶「Tampermonkey」を導入します

◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。

既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。 

拡張機能の導入については、以下のページに簡単な説明があるので参照ください。

 

 

❷「Tampermonkey」にスクリプトを登録します

◎「Tampermonkey」の「」マークの「新規スクリプト」タブを開きます。

 

 

 

◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。

 

 

〔 Dakuten ⭐ 〕 ver. 0.1

 

// ==UserScript==
// @name          Dakuten ⭐
// @namespace  http://tampermonkey.net/
// @version      0.1
// @description  編集枠(通常表示)で濁点・半濁点のチェック 「F10」ダブルキー押下
// @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 act_mode=0;
    let buffer;
    let hk; // ハイライト要素のインデックス
    let native_hk; // フォーカス要素のインデックス履歴
    let result_box;
    let count_t;

    let editor_iframe;
    let iframe_doc;
    let iframe_body;
    let iframe_html;

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

    catch_key();

    function catch_key(){
        document.onkeydown=function(event){
            check_key(event); }

        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){
            iframe_doc=editor_iframe.contentWindow.document;
            if(iframe_doc){
                iframe_doc.onkeydown=function(event){
                    check_key(event); }}}


        let clickCount=0;
        function check_key(event){
            if(event.keyCode==121){ //「F10」ダブルキー押下
                event.preventDefault();
                if(!clickCount){ // シングルキー押下の場合
                    ++clickCount;
                    setTimeout( function(){
                        clickCount=0;
                    }, 500 ); }
                else{ // ダブルキー押下の場合
                    clickCount=0;
                    check_act(); }}


            function check_act(){
                if(if_check()){
                    if(act_mode==0){
                        act_mode=1;
                        dis_html(0);
                        setTimeout(()=>{
                            check_text(); }, 20); }
                    else{
                        act_mode=0;
                        dis_html(1);
                        delete_mu();
                        remove_container(); }} }

        } // check_key()


        function if_check(){
            editor_iframe=document.querySelector('.cke_wysiwyg_frame');
            if(editor_iframe){
                return true; }
            else{
                return false; }}

        before_end(); // 編集終了時にマークを自動削除

    } // catch_key



    function dis_html(n){
        let editor_tab=document.querySelector('.p-editModeTab');
        if(editor_tab){
            if(n==0){
                editor_tab.style.display='none'; }
            else{
                editor_tab.style.display='block'; }}}



    function disp_container(){
        monitor.disconnect(); // MutationObserverを 起動表示に反応させない
        let insert_div=
            '<div id="cds_container">'+
            '<span id="cd_result"> </span>'+
            '<style>'+
            '#cds_container { position: absolute; top: 17px; left: 20px; '+
            'width: auto; padding: 3px 6px; background: #fff; '+
            'border: 1px solid #aaa; border-radius: 4px; z-index: 11; }'+
            '#cd_result { display: inline-block; min-width: 70px; padding: 4px 6px 2px; '+
            'border: 1px solid #aaa; font-size: 16px; }'+
            '</style></div>';

        let l_body=document.querySelector('body.l-body');
        if(!l_body.querySelector('#cds_container')){
            l_body.insertAdjacentHTML('beforeend', insert_div); }

        add_mu_style(); // muタグを設定

        monitor.observe(target, {childList: true});

    } // disp_container() 「開始処理」



    function remove_container(){
        let cds_container=document.querySelector('#cds_container');
        if(cds_container){
            cds_container.remove(); }}



    function check_text(){
        disp_container();

        editor_iframe=document.querySelector('.cke_wysiwyg_frame'); // ここで取得
        if(editor_iframe){ //「通常表示」が実行条件
            iframe_doc=editor_iframe.contentWindow.document;
            iframe_body=iframe_doc.querySelector('.cke_editable');
            buffer=iframe_body.innerHTML; // ハイライト表示のためソースコードを保存 🟦

            t_process();

            native_hk=-1;
            hk=0;
            next(hk); }


        function t_process(){
            let search_word=
                ["ぱ","ぴ","ぷ","ぺ","ぽ","ば","び","ぶ","べ","ぼ","パ","ピ","プ","ペ","ポ","バ","ビ","ブ","ベ","ボ"];
            let rep_word;
            let rep_buffer=buffer;
            for(let k=0; k<search_word.length; k++){
                rep_word='<mu>'+ search_word[k] +'</mu>';
                rep_buffer=rep_buffer.replace(new RegExp(search_word[k], 'g'), rep_word); }

            iframe_body.innerHTML=rep_buffer;
            let mu_all=iframe_body.querySelectorAll('mu');
            count_t=mu_all.length; }

    } // check_text()



    function next(hk){ //「巡回表示」「選択置換」コード
        result_box=document.querySelector('#cd_result');
        let mark=iframe_body.querySelectorAll('mu');

        if(native_hk!=-1){ // 基本的に前回のインデックスを再現🅿
            hk=native_hk; }
        else if(native_hk==-1 || !native_hk){ // 初期インデックス生成🅿
            if(mark.length==1){ hk=0; } // 1個なら即決定
            else{
                let near_n; // 中央後方の要素のインデックス
                let editor_hight=editor_iframe.clientHeight; // 編集枠の高さ
                for(let k=1; k<mark.length; k++){ // スクロール位置中央を越えるmark[k]を取得
                    if(mark[k].getBoundingClientRect().top>editor_hight/2){
                        near_n=k;
                        break; }}
                if(!near_n){ // スクロール位置中央より後方にmark[k]がない場合
                    hk=mark.length-1; }
                else{ // 直前の mark[k]と比較して、近い方を採る
                    if(mark[near_n].getBoundingClientRect().top>
                       editor_hight-mark[near_n-1].getBoundingClientRect().top){
                        hk=near_n-1; }
                    else{
                        hk=near_n; }}}}

        view(hk);
        try{
            mark[hk].classList.add("h"); } // 最初のハイライト色を変更
        catch(e){ ; }

        result_box.textContent='Count:'+count_t+'│'+(hk+1);

        document.addEventListener("keydown", check_arrow); // documentは先に指定
        iframe_doc=editor_iframe.contentWindow.document;
        if(iframe_doc){
            iframe_doc.addEventListener("keydown", check_arrow); }// iframeは後に指定

        function check_arrow(event){
            if(event.keyCode==38 && act_mode==1){ //「⇧」
                event.preventDefault();
                back(); }
            if(event.keyCode==37 && act_mode==1){ //「⇦」
                event.preventDefault();
                back(); }
            if(event.keyCode==40 && act_mode==1){ //「⇩」
                event.preventDefault();
                forward() }
            if(event.keyCode==39 && act_mode==1){ //「⇨」
                event.preventDefault();
                forward() }

            native_hk=hk;

            function back(){
                if(hk>0){ // 標準のハイライト色に戻す
                    mark[hk].classList.remove("h");
                    hk-=1; }
                else if(hk==0){
                    hk=0; }
                result_box.textContent='Count:'+count_t+'│'+(hk+1);
                try{
                    mark[hk].classList.add("h"); }
                catch(e){ ; }
                view(hk); }

            function forward(){
                if(hk<mark.length-1){ // 標準のハイライト色に戻す
                    mark[hk].classList.remove("h");
                    hk+=1; }
                else if(hk==mark.length-1){
                    hk=mark.length-1; }
                result_box.textContent='Count:'+count_t+'│'+(hk+1);
                try{
                    mark[hk].classList.add("h"); }
                catch(e){ ; }
                view(hk); }

        }} // next() インデックス取得🅿



    function view(hk){
        let l_body=document.querySelector('body.l-body');
        let mark=iframe_body.querySelectorAll('mu');
        try{
            mark[hk].scrollIntoView({block: "center"});
            iframe_html.scrollBy(0, -12); } // -1~-24  -12がクリープを無くす最適値
        catch(e){ ; }
        l_body.scrollIntoView(); }



    function add_mu_style(){
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){ //「通常表示」の場合
            iframe_doc=editor_iframe.contentWindow.document;
            iframe_html=iframe_doc.querySelector('html');
            let css_iframe=
                '.cke_editable mu { box-shadow: inset 0 -6px 0 -1px #ffcc00; } '+ // ハイライト muタグ背景色⭕
                '.cke_editable mu.h { box-shadow: inset 0 -6px 0 -1px red; }'; // フォーカス muタグ背景色⭕
            let style_tag_iframe=iframe_doc.createElement("style");
            style_tag_iframe.setAttribute("class", "ep");
            style_tag_iframe.appendChild(document.createTextNode(css_iframe));
            if(iframe_html.querySelector('.ep')){
                iframe_html.querySelector('.ep').remove(); }
            iframe_html.appendChild(style_tag_iframe); }}



    function delete_mu(){
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        if(editor_iframe){ //「通常表示」の場合
            iframe_doc=editor_iframe.contentWindow.document;
            iframe_body=iframe_doc.querySelector('.cke_editable');
            if(iframe_body){
                let mark=iframe_body.querySelectorAll('mu');
                if(mark.length!=0){
                    iframe_body.innerHTML=
                        iframe_body.innerHTML.replace(new RegExp('<mu.*?>', 'g'), ''); }}}}



    function before_end(){
        editor_iframe=document.querySelector('.cke_wysiwyg_frame');
        let submitButton=document.querySelectorAll('.js-submitButton');
        submitButton[0].addEventListener("mousedown", all_clear, false);
        submitButton[1].addEventListener("mousedown", all_clear, false);

        function all_clear(){
            if(!editor_iframe){ //「HTML表示」編集画面の場合
                alert("⛔ Dakuten ⭐ の終了処理ができません\n\n"+
                      "   通常表示画面に戻り 編集を終了してください");
                event.stopImmediatePropagation();
                event.preventDefault(); }

            if(editor_iframe){ //「通常表示」編集画面の場合
                if(act_mode==1){
                    dis_html(1);
                    delete_mu();
                    remove_container(); }}
        }} // before_end()

} // main()


 

 

 

「Dakuten ⭐」最新版について 

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

 

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