「svgタグ禁止」に対処する私の考え 

私は「svg画像」を記事中に多用し、また「svg画像」を使用する事の価値を評価して来たのですが、今回の「svgタグ禁止」によって足元をすくわれた思いです。 2日程をかけて、過去の全記事をチェックして来ましたが、幾つかの記事に関しては「svg画像」を削除すると記事が成り立たなくなるので、そのままにしています。 

 

「svg画像」を記事中で使ってこられたユーザーの場合は、私と同じ条件にあると思いますが、以下に私が妥当と思う対処について纏めます。

 

 

既に投稿した記事は無問題 

既に投稿した記事に関しては、「svg画像」は削除されずに表示され続ける様です。 これは、以下の私のページを参照されると確認できます。

 

 

この記事では、「Font Awesome 絵文字」「アメブロ絵文字」「svg画像のアイコン」の順にサンプル表示しています。

 

 

「再編集」は要注意 

「svg画像」を含んだ記事を「再編集」で開いた後は、「禁止タグチェック」で「投稿」できなくなります。 その際に「下書き保存」は可能ですが、安易に「下書き保存」を選択するのは要注意 です。

 

◎ 編集を放棄して「編集画面を閉じる」と、元の記事は「再編集の編集画面」を開く前の「公開」された状態で残ります。

 

◎「下書き保存」をすると、「svg画像」を全て削除しない限り「公開」できなくなります。

 

「svg画像」を削除すると記事の主旨が成り立たない記事の場合は、「下書き保存」をせずに 編集画面のブラウザを「✖」閉じるのが賢明と思います。

 

 

編集開始時にチェックする対策ツールは有効 

安易に「下書き保存」をして「公開」が出来なく場合を防ぐ意味で、前ページで紹介した対策ツールは有効です。

 

 

「SVG Repair ⭐」を常駐しておけば、再編集で編集画面を開いた時に、手作業で「削除」または「置換え」が必要な「svg画像」の有無が判ります。 多くの編集を行った後で「svgタグ」の問題が判るより、先ず「記事を触らないでおく」のか「svg画像の処理をする」のかを選択できる方が、良いに決まっています。

 

 

 

 ブログの全記事で「svg」の有無をチェックする

一般の方には、殆ど必要のない作業と思いますが、「svg画像」を記事中で使ってこられたユーザーは、今後の方針変更をせざるを得なくなると思います。

 

私は、過去の記事の「再編集」や「複製」をする事が多くあります。 その場合、先の対策ツール「SVG Repair ⭐」があれば、おうよその場合に対処できると思います。 しかし、このツールが教えてくれる前に、全記事の処理をしておこうと考えました。

 

また、実際に「svg画像」の処理を経験すれば、対策ツールの改善点や、必要な追加対策を見いだせるので、全記事を対象とした処理を行う事にしました。

 

「リンクカード」の「svgのリンクマーク」

「svgのリンクマーク」には「SVG Repair ⭐」が満足な処理が出来ます。 全記事中の全ての「リンクカード」を処理するのは能力の上限を超えるので、これは過去記事の「再編集」や「複製後の再編集」の際に、このツールの自動処理に任せて良いと考えました。

 

上記以外の「svg画像」

私の場合は、SVG画像に関する記事上のサンプルの「svg画像」や、ツールの説明などでアイコンボタンを表示する「 」などに「svg画像」を使って来ました。

 

今後、過去記事の利用で問題になるのは後者で、この種の「svg画像」が使用されている記事数は数百程度でした。(後で判った事ですが)

 

で、これらを全記事(2000件程度)から探す必要がありました。 これは、従来の経験から、「Every Page Worker 💢💢」をアレンジして処理を行う事にしました。

 

 

 

 

「Every Page Worker 💢💢 Check SVG」 ver. 4.6 

ツール名は「Every Page Worker 💢💢 Check SVG」としましたが、バージョンはベースのコードから引き継いでいます。

 

各記事で以下の2種のチェックを行います。

 Check❶ 「リンクマーク」に「svg画像」を使用している記事

 Check❷ 「リンクマーク」以外の「svg画像」を使用した記事 

 

このツールは「記事の編集・削除」のページで、各記事の検索を自動実行します。

▪途中で自動の処理の一旦停止ができ、またそれ以降の再開が可能です。

▪処理範囲は、処理開始を押したページ以降 ~ 最終(最近)の記事です。

▪最初は、使い方の要領を得るため、最近のページでテストをしてください。

▪このツールは各記事を小型の編集画面「処理ウインドウ」に開いて検索しますが、検索後に記事を保存をしないので、記事内容を損なう事はない設計です。

 

 

 使用上の注意

このツールは「記事の編集・削除」のページで動作します。

 

◎ツールを「ON」とすると、「記事の編集・削除」の画面を処理目的のためにアレンジします。 ツール「OFF」で元の「記事の編集・削除」のデザインに戻ります。

 

 

 

◎ツールを「ON」とすると、編集画面など関連画面の動作が変わります。 従って、このツールでの作業終了後は、速やかに必ずツールを「OFF」にしてください。

 

「SVG Repair ⭐」は必ず「OFF」にして検索を開始します。「ON」のまま検索を実行すると、「リンクマーク」(Check❶)は「無し」の結果になります。 それは、「SVG Repair ⭐」が先にリンクマークの置換え処理をしてしまうからです。

 

 

ウインドウの配置 

下は検索を実行中の状態で、左側は「処理ウインドウ」です。 ツールは「記事の編集・削除」のリストを順番に「処理ウインドウ」に開いて検索を実行します。

 

 

 

「処理ウインドウ」が検索時に開くので、「記事の編集・削除」のウインドウは、デスクトップの右側半分に置く様にしてください。 ツールの操作は、上図の「コントロール」の部分で行います。

 

 

コントロール 

以下は、このツールのコントロール部です。 

 

◎ コントロールの上側に「表示年度/月」と「月内のページャー」が表示されます。 この部分は、通常の通りに表示月を選択する操作が出来ます。

 

 

 

「自動処理を開始」するボタンです。 処理が開始されると、ボタンは「一旦停止」のボタンに変わります。 一旦停止時は「自動処理の再開」のボタンになります。

 

 

 

「svg画像」が検索された記事のIDと検索種(Check❶ / Check❷)は、ローカルストレージに記録されます。「初期化」ボタンは、このローカルストレージの記録を全てクリアしますが、それまでの検索を全てやりなおす際に必要です。

 

 ローカルストレージの記録はブラウザを閉じても消えませんが、特にデータを残して置きたい場合にファイル化が可能です。 このボタンを押すと、検索し記録したデータをダウンロードフォルダーにテキストファイルで保存します。

 

 ファイル化したデータをツールに呼び戻すボタンです。 それまでのローカストレージの記録内容は、読込んだデータで上書きされます。

 

 検出された総記事数です。(1記事に ❶ ❷ がある場合は記事数は1です)

 

 Check❶ 「svgのリンクマーク」を含む記事の数です。 検索処理中は、発見する度に値が更新されます。 検索処理後は、この枠は記事の選択枠になります。 枠内の数は「記事発見の順番」を意味し、この数で記事を指定します。

 

 左の 枠で指定した記事を編集画面に開くボタンです。 編集画面は通常のサイズで開きます。

 

 Check❷ 「リンクマーク以外のsvg画像」を含む記事の数で、発見した記事を選択して編集画面に開くことが出来ます。

 

 左の 枠で指定した記事を編集画面に開くボタンです。

 

 

 「svg画像」の検索方法

●「記事の編集・削除」で開いたページで を押して処理を開始すると、それ以降の年/月のページを自動的に開き、処理を続けます。 最終的には最後(最近)のページまで処理をして、自動的に終了します。

▪スタートしたページより旧い時期の記事は処理をしません。

のボタンを「Ctrl+左Click」して処理を開始すると、リスト上の任意の記事を「左Click」で指定して、その記事から自動処理を開始する事ができます。

 

● のボタンで「一旦停止」したり、途中でブラウザを閉じて、処理を中断できます。 ストレージには、常に処理した範囲のデータが残ります。

▪一定期間を処理して、他の範囲を後で追加処理して範囲を広げる事が可能です。

▪データは上書きで追加・更新され、同じ範囲を重複処理しても問題はありません。

 

● 処理対象は「最新版エディタ」で開かれる記事のみで、「タグ編集エディタ」で開かれる記事は処理せずに閉じます。 また、記事の公開設定の「全員に公開」「下書き」「アメンバー限定公開」などには関係なく、全てを処理します。

 

●「svg画像」の検出が記録されると「初期化」をするまで記録が残ります。 

▪記事から「svg画像」を削除して更新した場合は、再びその記事のページを検索処理した時に記録が消えます。 

 

● ブラウザのポップアップブロックが有効になっていると、このツールが「処理ウインドウ」を開く動作が妨げられます。 ブラウザのポップアップブロックの設定を開き、「https://blog.ameba.jp」を ポップアップ許可URLに追加してください。

 

● 環境により差が生じますが、1記事を4~ 8sec程度で処理します。 自動処理動作中は、ブラウザの作業がツールに専有され、他の作業が出来なくなります。

 

● 通信状況などが原因して、連続処理が停止する場合があります。 

▪動作停止時は、処理ウインドウを「✖」で閉じ、停止した「記事の編集・削除」のページを「 」リロードして、そのページから を押し処理を開始してください。

▪連続動作は数秒間停止した様に見える場合があります。

▪20sec程度待っても新しい処理ウインドウが開かない場合は、停止と思われます。

 

 

検索結果を手作業の処理に利用する 

連続の検索処理が進行中は、処理済の記事に淡いグリーンの背景色が着きます。

 

 

 

検索処理の一旦停止時や終了後では、「記事の編集・削除」の「表示年度/月」の選択によって、各月の記事の検索結果を閲覧できます。

 

 

 

各記事の行の右端の ❶ ❷ のマークは「svg画像」の検出を表します。

 

  は Check❶ 「リンクマークのsvg画像」があります。

  は Check❷ 「リンクマーク以外のsvg画像」があります。

 

 

 

通常は「リンクマーク以外のsvg画像」が問題になります。 それを含む「」が表示された記事は、再編集時に手作業による「svg画像」の処理が必要になります。

 

各行の「  編集」ボタンから、記事の編集画面を開き「svg画像」処理が出来ます。

 

 

編集画面の開き方 

●既に連続の「svg画像」の検索の処理が終わっている場合は、「SVG Repair ⭐」を「ON」にして、各記事の処理が出来ます。

 

 

 

編集画面を開く「  編集」ボタンのクリック操作で、ボタンの横に「青マーク」が表示されます。 これは、処理済と未処理の区別をするためです。 ただし、この表示は簡易機能で、ページをリロードしたり移動すると「青マーク」がリセットされます。 その場合は、処理済のマークがなくなる事に注意してください。

 

●「青マーク」を利用するには、「  編集」ボタンを「左Click」して「編集画面」を開いてください。 編集画面は別タブに開きます。

▪ 編集処理後に不要となったタブは閉じてもOKです。 ただし、元の画面(上図)を閉じると「青マーク」がリセットされるので注意してください。

 

● 各記事を編集して「svg画像」を削除しても「❶ ❷」のマークは消えません。 このマークは、この記事を含むページの検索処理をもういちど実行した時に消えます。

 

 

 

「Every Page Worker 💢💢 Check SVG」を利用するには

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

 

❶「Tampermonkey」を導入します

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

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

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

 

 

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

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

 

 

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

 

〔コピー方法〕 右サイドバーの   マークのボタンを1度押してください。

 コード枠内の右クリック ➔ コード全体の選択 ➔ コピー操作 が可能になります。

 

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

 

 

〔 Every Page Worker 💢💢 Check SVG 〕 ver. 4.7

 

// ==UserScript==
// @name          Every Page Worker 💢💢 Check SVG
// @namespace  http://tampermonkey.net/
// @version       4.7
// @description  ブログ全記事を開いてimg[contenteditable="inherit"] の有無を検索
// @author        Ameba Blog User
// @match        https://blog.ameba.jp/ucs/entry/srventrylist*
// @match        https://blog.ameba.jp/ucs/entry/srventryupdate*
// @run-at        document-start
// @grant         none
// ==/UserScript==


window.addEventListener('DOMContentLoaded', function(){ // CSSデザインを適用するためのスクリプト
    let body_id=document.body.getAttribute('id');
    if(body_id=='entryListEdit'){ //「記事の編集・削除」の画面にのみCSSを適用

        let style=
            '<style>'+
            '.include-ex-linkBtn, .save-browserPush, .save-gsc, .save-hashtag-module, '+
            '.adcrossBanner { display: none; } '+
            '#globalHeader, #ucsHeader, #ucsMainLeft h1, .l-ucs-sidemenu-area, #ucsMainRight, '+
            '#entryList dl, #entryList .rightCol input, .actionControl, '+
            '#footerAd, #globalFooter, .checkboxAllControl { display: none !important; } '+
            '#entryList .selection-bar { display: none; } '+

            '#ucsContent { width: 840px !important; background: #fff; '+
            'box-shadow: 0 0 0 100vh #c5d8e1; border-radius: 0; } '+
            '#ucsContent::before { content: unset; } '+
            '#ucsMain { margin-top: 15px; padding: 0 !important; background: #fff; border-radius: 0; } '+
            '#ucsMainLeft { width: 838px !important; padding: 0 15px; float: none; } '+

            '#entryList li{ height: 24px; padding: 8px 5px 5px !important; } '+
            '#entryList li:hover { background-color: #e2eef0; } '+
            '#entryList li .entry-column { padding-left: 16px !important; } '+

            '#entryList .leftCol, #entryList .titleCol h2 { width: 440px !important; line-height: 24px; } '+
            '.leftCol a { text-decoration: none !important; } .leftCol a:visited { color: #3970b5; } '+
            '#entryList .rightCol { display: flex; width: 320px !important; '+
            'flex-direction: row; margin-top: -2px; margin-left: 0; } '+
            '#entryList .txtCol { white-space: nowrap; font-size: 13px; '+
            'margin-top: 4px; margin-bottom: 2px; line-height: 16px; } '+
            '#entryList .status-text { width: 64px; margin-bottom: -4px; padding: 2px 4px 0; '+
            'font-weight: normal; color: #000; } '+
            '#entryList .txtCol .date { display: inline-block; padding: 2px 4px 0; font-size: 13px; '+
            'color: #000; } '+
            '#entryList .deleteCol { margin: 0 10px; } '+
            '.deleteCol a:nth-child(2), .deleteCol a:nth-child(3), .rightCol input { '+
            'display: none !important; } '+
            '#entryList .deleteCol a { padding: 2px 5px 0; font-size: 14px; '+
            'text-decoration: none !important; border: 1px solid #aaa; border-radius: 4px; '+
            'background: linear-gradient(0deg, #eee, #fff); } '+
            '#entryList .deleteCol a:hover { outline: auto #1976d2; } '+
            '#entryList .deleteCol .process svg { width: 16px; height: 16px; } '+

            '#entryList ul input[value="1"] + input + li .txtCol span:first-child { display: inline-block; '+
            'text-indent: 12px; color: #fff; background: #2196f3 !important; } '+
            '#entryList ul input[value="2"] + input + li .txtCol span:first-child { display: inline-block; '+
            'text-indent: 2px; overflow: hidden; color: #fff; background: #009688 !important; } '+

            '#entrySort { margin-bottom: 2px; } '+
            '#entryMonth { font-size: 14px; overflow: visible; margin-top: 3px; } '+
            '#entryMonth li, #entryMonth #nowMonthLi { padding: 2px 10px 0; } '+
            '#nowMonth { padding: 1px 6px 0; border: none; border-radius: 1px; '+
            'box-shadow: 0 0 0 2px #0066cc; color: #000; } '+
            '#entryListEdit form { display: flex; flex-direction: column; } #entrySort { order: -2; } '+
            '.pagingArea { order: -1; margin-bottom: -33px; position:unset !important; } '+
            '.pagingArea a { border: 1px solid #888; } .pagingArea .active{ border: 2px solid #0066cc; } '+
            '.pagingArea a, .pagingArea .active, .pagingArea .disabled { font-size: 14px; line-height: 23px; } '+

            '#sorting { margin: 36px 0 4px; padding: 2px 0; height: 78px; background: #ddedf3; } '+
            '#sorting select, #sorting ul { display: none; } '+
            '#div0 { color: #333; font-size: 14px; margin: 0 -10px 0 15px; } '+
            '#div1 { color: #000; font-size: 14px; margin: 1px 15px; background: #c0dbed; } '+
            '#list_snap { padding: 2px 0 0; margin: 7px 20px 7px 0; width: 180px; } '+
            '#reset { padding: 2px 0 0; margin-right: 20px; width: 60px; } '+
            '#export { padding: 2px 0 0; margin: 7px 10px 7px 0; width: 100px; } '+
            '.snap_result { display: inline-block; margin: 6px 4px 4px 12px; } '+
            '.num { padding: 2px 2px 0 6px; width: 40px; } '+
            '.editor_open { padding: 2px 0 0; margin: 0 20px 0 4px; width: 50px; } '+
            'input { font-family: meiryo; font-size: 14px; } '+
            '.ch1, .ch2 { font: 15px/25px Meiryo; color: #0277bd; opacity: 0; }'+
            '</style>';

        document.head.insertAdjacentHTML('beforeend', style);

        let rightCol=document.querySelectorAll('#entryList .rightCol');
        for(let k=0; k<rightCol.length; k++){
            let iAH='<span class="ch1">❶</span><span class="ch2">❷</span>';
            rightCol[k].insertAdjacentHTML('beforeend', iAH); }

    }})


window.addEventListener('load', function(){ // このスクリプトは親ウインドウで働くメインスクリプト
    let body_id=document.body.getAttribute('id');
    if(body_id=='entryListEdit'){ // 親ウインドウの条件

        let drive_mode; // ページ更新時の動作モード
        let blogDB={}; //「対象記事のID/チェックフラグ または内容」の記録配列

        let entry_id_DB; // ID検索用の配列
        let pub_1; // flag 1 が記録された記事総数
        let pub_2; // flag 2 が記録された記事総数

        let entry_id;
        let entry_target;
        let list_bar;
        let editor_flg;

        let next_target; // ページ内の次の対象記事
        let new_win;
        let link_target;
        let editor_iframe;
        let iframe_doc;

        let ua=0;
        let agent=window.navigator.userAgent.toLowerCase();
        if(agent.indexOf('firefox') > -1){ ua=1; } // Firefoxの場合のフラグ
        if(agent.indexOf('edge') > -1){ ua=2; } // Edgeの場合のフラグ


        let read_json=localStorage.getItem('EPW_DB_back'); // ローカルストレージ 保存名
        blogDB=JSON.parse(read_json);
        if(blogDB==null){
            blogDB=[['epw00000000', 's', 0]]; }
        drive_mode=blogDB[0][1]; // 起動時に動作フラグを取得
        blogDB[0][1]='s'; // リロード時等のためにリセット
        let write_json=JSON.stringify(blogDB);
        localStorage.setItem('EPW_DB_back', write_json); // ローカルストレージ 保存

        reg_set();

        function reg_set(){
            let k;
            entry_id_DB=[]; // リセット
            pub_1=0;
            pub_2=0;

            for(k=0; k<blogDB.length; k++){
                entry_id_DB[k]=blogDB[k][0]; // ID検索用の配列を作成
                if(blogDB[k][1]=='1'){
                    pub_1 +=1; } // flag 1 が記録された記事総数(検索1)
                if(blogDB[k][2]=='1'){
                    pub_2 +=1; }}} // flag 2 が記録された記事総数(検索2)


        entry_id=document.querySelectorAll('input[name="entry_id"]');
        entry_target=document.querySelectorAll('.deleteCol');
        list_bar=document.querySelectorAll('#entryList li');


        control_pannel(drive_mode);

        hit_display();

        function control_pannel(dm){
            let sty;
            let insert_div0;
            insert_div0=document.createElement('div');
            insert_div0.setAttribute('id', 'div0');
            let box=document.querySelector('#sorting');
            box.appendChild(insert_div0);

            let insert_div1;
            insert_div1=document.createElement('div');
            insert_div1.setAttribute('id', 'div1');
            box.appendChild(insert_div1);

            let button1=document.createElement('input');
            button1.setAttribute('id', 'list_snap');
            button1.setAttribute('type', 'submit');
            insert_div0.appendChild(button1);
            if(dm=='s'){
                button1.setAttribute('value', '全記事へ処理を開始 ▶'); }
            else if(dm=='c'){
                button1.setAttribute('value', ' 処理を一旦停止  ❚❚'); }
            else if(dm=='e'){
                button1.setAttribute('value', '処理が全て終了しました'); }

            button1.addEventListener('click', function(e){
                e.preventDefault();
                if(e.ctrlKey){
                    start_stop(1); } // ページの途中から連続処理スタート
                else{
                    start_stop(0); }}, false);


            function start_stop(n){
                if(drive_mode=='s'){ // 最初の起動直後
                    let conf_str='   🔴 このページ以降の記事に連続した処理を実行します'+
                        '\n\n      停止ボタンのクリックで処理停止/処理再開ができます';
                    let ok=confirm(conf_str);
                    if(ok){
                        drive_mode='c'; // ページ内の連続処理
                        button1.setAttribute('value', ' 処理を一旦停止  ❚❚');
                        if(n==0){
                            next(0); }
                        else{
                            alert(' 処理を開始する記事を左クリックしてください');
                            clicked_item(); }}}

                else if(drive_mode=='c'){ // 連続動作状態の場合
                    drive_mode='p'; // クリックされたら「p」停止モード
                    button1.setAttribute('value', ' 処理を再開する  ▶'); }

                else if(drive_mode=='p'){ // 動作停止状態の場合
                    drive_mode='c'; // クリックされたら連続動作を再開
                    button1.setAttribute('value', ' 処理を一旦停止  ❚❚');
                    open_win(next_target); }

                function clicked_item(){
                    let entry_item=document.querySelectorAll('.entry-item');
                    for(let k=0; k<entry_item.length; k++){
                        entry_item[k].onclick=function(e){
                            e.preventDefault();
                            e.stopImmediatePropagation();
                            next(k); }}}
            } // start_stop()


            if(dm=='c'){ // ページを開いた時に「c」は連続動作
                setTimeout(next(0), 200); } // 「c」連続動作はぺージ遷移時 0.2sec で自動実行 ⭕
            else if(dm=='e'){ // 「e」は終了
                button1.style.pointerEvents='none'; }


            let button2=document.createElement('input');
            button2.setAttribute('id', 'reset');
            button2.setAttribute('type', 'submit');
            button2.setAttribute('value', '初期化');
            insert_div0.appendChild(button2);

            button2.onclick=function(e){
                e.preventDefault();
                blogDB=[['epw00000000', 's', 0]];
                let write_json=JSON.stringify(blogDB);
                localStorage.setItem('EPW_DB_back', write_json); // ローカルストレージ保存
                snap_disp();
                hit_display_clear();
                document.querySelector('#reset').value='〔 〕'; }

            let button3=document.createElement('input');
            button3.setAttribute('id', 'export');
            button3.setAttribute('type', 'submit');
            button3.setAttribute('value', 'ファイル保存');
            insert_div0.appendChild(button3);

            button3.onclick=function(e){
                e.preventDefault();
                let write_json=JSON.stringify(blogDB);
                let blob=new Blob([write_json], {type: 'application/json'});
                if(ua==2){
                    window.navigator.msSaveBlob(blob, 'EPW.json'); } // 保存ファイル名
                else{
                    let a_elem=document.createElement('a');
                    a_elem.href=URL.createObjectURL(blob);
                    a_elem.download='EPW.json'; // 保存ファイル名
                    if(ua==1){
                        a_elem.target='_blank';
                        document.body.appendChild(a_elem); }
                    a_elem.click();
                    if(ua==1){
                        document.body.removeChild(a_elem); }
                    URL.revokeObjectURL(a_elem.href); }}

            let button4=document.createElement('input');
            button4.setAttribute('type', 'file');
            button4.setAttribute('style', 'vertical-align: 1px; width: 390px');
            if(ua==2){
                button4.setAttribute('style', 'vertical-align: 0; width: 270px; direction: rtl'); }
            insert_div0.appendChild(button4);

            button4.addEventListener("change", function(){
                if(!(button4.value)) return; // ファイルが選択されない場合
                let file_list=button4.files;
                if(!file_list) return; // ファイルリストが選択されない場合
                let file=file_list[0];
                if(!file) return; // ファイルが無い場合

                let file_reader=new FileReader();
                file_reader.readAsText(file);
                file_reader.onload=function(){
                    if(file_reader.result.slice(0, 15)=='[["epw00000000"'){ // EPW.jsonの確認
                        let data_in=JSON.parse(file_reader.result);
                        blogDB=data_in; // 読込み上書き処理
                        let write_json=JSON.stringify(blogDB);
                        localStorage.setItem('EPW_DB_back', write_json); // ローカルストレージ 保存
                        button2.setAttribute('value', '初期化'); // 初期化後なら読み込んだ事を示す
                        snap_disp(); }
                    else{
                        alert("   ⛔ 不適合なファイルです  EPW.json ファイルを選択してください");}};});

            let span5=document.createElement('span');
            span5.setAttribute('id', 'snap_result1');
            span5.setAttribute('class', 'snap_result');
            insert_div1.appendChild(span5);

            let button6=document.createElement('input');
            button6.setAttribute('id', 'num_1');
            button6.setAttribute('class', 'num');
            button6.setAttribute('type', 'number');
            button6.setAttribute('min', '0');
            insert_div1.appendChild(button6);

            let button7=document.createElement('input');
            button7.setAttribute('class', 'editor_open');
            button7.setAttribute('type', 'submit');
            button7.setAttribute('value', '編集');
            insert_div1.appendChild(button7);

            button7.onclick=function(e){
                e.preventDefault();
                let k;
                let pub_1_DB=[]; // pub_1 の entry_id の配列
                if(pub_1>0){
                    for(k=0; k<blogDB.length; k++){
                        if(blogDB[k][1]=='1'){
                            pub_1_DB.push(blogDB[k][0]); }}

                    if(button6.value>0){
                        let open_id=pub_1_DB[button6.value -1];
                        let pass=
                            'https://blog.ameba.jp/ucs/entry/srventryupdateinput.do?id='+ open_id;
                        let win_option='top=20, left=40, width=1020, height=900';
                        window.open(pass, button6.value, win_option); }}}

            let span8=document.createElement('span');
            span8.setAttribute('id', 'snap_result2');
            span8.setAttribute('class', 'snap_result');
            insert_div1.appendChild(span8);

            let button9=document.createElement('input');
            button9.setAttribute('id', 'num_2');
            button9.setAttribute('class', 'num');
            button9.setAttribute('type', 'number');
            button9.setAttribute('min', '0');
            insert_div1.appendChild(button9);

            let button10=document.createElement('input');
            button10.setAttribute('class', 'editor_open');
            button10.setAttribute('type', 'submit');
            button10.setAttribute('value', '編集');
            insert_div1.appendChild(button10);

            button10.onclick=function(e){
                e.preventDefault();
                let k;
                let pub_2_DB=[]; // pub_2 の entry_id の配列
                if(pub_2>0){
                    for(k=0; k<blogDB.length; k++){
                        if(blogDB[k][2]=='1'){
                            pub_2_DB.push(blogDB[k][0]); }}

                    if(button9.value>0){
                        let open_id=pub_2_DB[button9.value -1];
                        let pass=
                            'https://blog.ameba.jp/ucs/entry/srventryupdateinput.do?id='+ open_id;
                        let win_option='top=20, left=40, width=1020, height=900';
                        window.open(pass, button9.value, win_option); }}}

            snap_disp();

        } // control_pannel()


        function snap_disp(){
            reg_set();
            let span5=document.querySelector('#snap_result1');
            span5.textContent='記録件数:' + (blogDB.length -1) + '   Check ❶:';
            let button6=document.querySelector('#num_1');
            button6.value=pub_1;
            button6.max=pub_1;
            let span8=document.querySelector('#snap_result2');
            span8.textContent='Check ❷:';
            let button9=document.querySelector('#num_2');
            button9.value=pub_2;
            button9.max=pub_2; }


        function hit_display(){
            let ch1=document.querySelectorAll('.ch1');
            let ch2=document.querySelectorAll('.ch2');
            for(let k=0; k<ch1.length; k++){
                let index=entry_id_DB.indexOf(entry_id[k].value);
                if(index!=-1){ // IDがblogDBに記録されていた場合
                    if(blogDB[index][1]==1){
                        ch1[k].style.opacity='1'; }
                    else{
                        ch1[k].style.opacity='0'; }
                    if(blogDB[index][2]==1){
                        ch2[k].style.opacity='1'; }
                    else{
                        ch2[k].style.opacity='0'; }}
                else{ // IDがblogDBに記録がない場合
                    ch1[k].style.opacity='0';
                    ch2[k].style.opacity='0'; }}}


        function hit_display_clear(){
            let ch1=document.querySelectorAll('.ch1');
            let ch2=document.querySelectorAll('.ch2');
            for(let k=0; k<ch1.length; k++){
                ch1[k].style.opacity='0';
                ch2[k].style.opacity='0'; }}


        function next(x){ // xはページ内の記事index[0~length-1]
            entry_id=document.querySelectorAll('input[name="entry_id"]');
            if(entry_id.length >x){
                open_win(x); } // 投稿記事がある場合 open_win を開始
            else{
                next_call();}} // 投稿記事が無ければ 次ページをcall する


        function open_win(k){
            next_target=k; // 送信完了までは未処理とする

            new_win=Array(entry_target.length);
            link_target=Array(entry_target.length);
            link_target[k]=entry_target[k].getElementsByTagName('a')[0].getAttribute('href');

            if(drive_mode=='c'){ // 処理ウインドウのサイズや位置の指定 ⬛🟧⬛
                let win_option='top=20, left=40, width=800, height=300';
                new_win[k]=window.open(link_target[k], k, win_option);

                list_bar[k].style.boxShadow='inset 0 0 0 2px #03a9f4'; // リスト欄に青枠表示
                new_win[k].addEventListener('load', work, false); } // 子ウインドウの処理 🟦


            function work(){
                let editor_flg=new_win[k].document.querySelector('input[name="editor_flg"]');
                if(editor_flg.value=="5"){ // 最新版エディタの文書の場合のみ処理
                    let interval=setInterval(find_iframe, 10); // iframe 読込み待機コード 🟥
                    function find_iframe(){
                        let editor_iframe=new_win[k].document.querySelector('.cke_wysiwyg_frame');
                        if(editor_iframe){
                            let iframe_doc=editor_iframe.contentWindow.document;
                            if(iframe_doc){
                                clearInterval(interval);
                                task();

                                function task(){ // taskは自動で開いたページでの作業コード / 作業目的で自製 🟥
                                    Promise.all([
                                        task_in1(),
                                        strage_write(),
                                        snap_disp(),
                                        hit_display() ])
                                        .then(end_target()) }


                                // svg画像 の有無を調べる ⬛🟧⬛

                                function task_in1(){ // ブログ本文の検索
                                    let result1=0; // リンクカードのsvg
                                    let result2=0; // リンクカードではないsvg

                                    let iframe_body=iframe_doc.querySelector('.cke_editable');
                                    let img_s=iframe_body.querySelectorAll('svg'); // svg画像を全検索
                                    for(let k=0; k<img_s.length; k++){
                                        let parent_ogp=img_s[k].closest('.ogpCard_link');
                                        if(parent_ogp){
                                            result1=1; } // 検索1:結果「flag 1」リンクカード ⬛🟧⬛
                                        else{
                                            result2=1; }} // 検索2:結果「flag 2」非リンクカード⬛🟧⬛

                                    if( result1==1 || result2==1){
                                        let index=entry_id_DB.indexOf(entry_id[k].value);
                                        if(index==-1){ // IDがblogDBに記録されていない場合
                                            blogDB.push([entry_id[k].value, result1, result2]); } // 記事ID/フラグ追加

                                        else{ // IDがblogDBに記録されていた場合
                                            blogDB[index][1]= result1; // 記事ID/フラグ「1」を更新
                                            blogDB[index][2]= result2; }} // 記事ID/フラグ「2」を更新
                                    else{
                                        let index=entry_id_DB.indexOf(entry_id[k].value);
                                        if(index!=-1){ // IDがblogDBに記録されていた場合
                                            blogDB.splice(index, 1); }} // 該当する登録を削除

                                    reg_set(); }


                                function strage_write(){
                                    let write_json=JSON.stringify(blogDB);
                                    localStorage.setItem('EPW_DB_back', write_json); }// ストレージ保存
                            }}}}
                else{
                    end_target(); }
            } // work()


            function end_target(){ // 終了処理
                let editor_flg=new_win[k].document.querySelector('input[name="editor_flg"]');
                list_bar[k].style.boxShadow='none';
                if(editor_flg.value=='5'){
                    list_bar[k].style.background='#caedf2'; }
                else{
                    list_bar[k].style.background='#eceff1'; }

                new_win[k].close();
                setTimeout(()=>{
                    next_do(k); }, 10); //⏩

                function next_do(k){
                    next_target=k+1;
                    if(next_target<entry_target.length){ open_win(next_target); }
                    else{ next_call(); }}} // ページの終りまで終了した状態

        } // open_win()


        function next_call(){
            let win_url;
            let current;
            let pageid;
            let next_url;
            let pager;
            let end;

            blogDB[0][1]='c'; // 連続動作フラグを連続にセット
            let write_json=JSON.stringify(blogDB);
            localStorage.setItem('EPW_DB_back', write_json); // ローカルストレージ保存

            win_url=window.location.search.substring(1,window.location.search.length);
            if(!win_url){
                current=now_curr(); } // 記事の編集・削除を開いた初期画面の場合
            else{
                current=win_url.slice(-6); }

            if(win_url.indexOf('pageID') ==-1){ // pageIDが無い 月のトップページの場合
                pager=document.querySelector('.pagingArea');
                if(pager){ // ページャーが有りその末尾でない場合 同月次ページへ
                    next_url=
                        'https://blog.ameba.jp/ucs/entry/srventrylist.do?pageID=2&entry_ym=' + current;
                    window.open( next_url, '_self'); }
                else{ // ページャーが無ければ次月トップページへ
                    current=make_next(current);
                    if(current!=0){ // 現在を越えないなら次月へ
                        next_url=
                            'https://blog.ameba.jp/ucs/entry/srventrylist.do?entry_ym=' + current;
                        window.open( next_url, '_self'); }
                    else{ // 現在を越えたら0が戻り停止
                        when_edge(); }}}

            else{ // pageIDを含み 月のトップページでない場合
                end=document.querySelector('.pagingArea .disabled.next');
                if(!end){ // ページャーの末尾でなければ同月次ページへ
                    pageid=parseInt(win_url.slice(7).slice(0, -16), 10) +1;
                    next_url=
                        'https://blog.ameba.jp/ucs/entry/srventrylist.do?pageID='+ pageid + '&entry_ym=' + current;
                    window.open( next_url, '_self'); }
                else{ // ページャーの末尾なら次月トップページへ
                    current=make_next(current);
                    if(current!=0){ // 現在を越えないなら次月へ
                        next_url=
                            'https://blog.ameba.jp/ucs/entry/srventrylist.do?entry_ym=' + current;
                        window.open( next_url, '_self'); }
                    else{ // 現在を越えたら0が戻り停止
                        when_edge(); }}}

            function make_next(curr){
                let ym;
                let y;
                let m;
                ym=parseInt(curr, 10); // 10進数値化
                y=Math.floor(ym/100); // 年は100で割った商
                m=ym % 100; // 月は100で割った余り
                if(m !=12){
                    ym=100*y + m +1; }
                else{
                    ym=100*y + 101; }

                if(ym > now_curr()){
                    return 0; } // 現在の月を越える場合は0を返す
                else{
                    return ym; }} // 次年月の数値を返す

            function when_edge(){
                blogDB[0][1]='s'; // 連続動作フラグをリセット
                let write_json=JSON.stringify(blogDB);
                localStorage.setItem('EPW_DB_back', write_json); // ローカルストレージ保存
                document.querySelector('#div0').remove();
                document.querySelector('#div1').remove();
                control_pannel('e'); } // 全作業の終了時の表示をさせる
        } // next_call()


        function now_curr(){
            let now=new Date();
            let curr=100*now.getFullYear() + 1*now.getMonth() +1;
            return curr; }


        // 編集済みの記事にマークを付ける
        let ed_sw=document.querySelectorAll('.deleteCol');
        for(let k=0; k<ed_sw.length; k++){
            ed_sw[k].onmousedown=()=>{
                ed_sw[k].style.boxShadow='8px 0 0 0 #2196f3'; }}

        let ed_link=document.querySelectorAll('.deleteCol a:first-child');
        for(let k=0; k<ed_link.length; k++){
            ed_link[k].setAttribute('target', '_blank'); }

    } // 親ウインドウの条件
})


 

〔追記〕2023.12.01

ver.4.6 ➔ ver. 4.7 に更新しました。

「リストの任意の記事から処理開始」「別タブに編集画面を開く」の機能を追加しました。 上記コードは更新済です。