ike81818
@ike81818

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

外部ファイルの内容が更新されたら、JavaScriptの処理を走らせたいです

解決したいこと

外部テキストファイルの内容を手動で更新保存したときに、
JavaScriptの処理が実行されるような実装をしたいです。

現状

現在、ブラウザ上に特定の文字(除外文字)を表示させないようにするプログラムを作成しています。

処理手順

1.除外文字をjogai.txtというテキストファイルに入力し保存します。
スクリーンショット 2022-07-31 19.50.19.png

2.下記のhtmlファイルをブラウザ上に貼り付けます。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>キーワード除外</title>
    <!-- <script src="read.js"></script> -->
  </head>
  <body>
    <input type="file" name="file" id="file" />
  </body>
</html>

<script>
  document.getElementById("file").onchange = function () {
    //除外キーワードをユニコードエスケープ形式\u0000に変換する
    const file = this.files[0];
    const reader = new FileReader();
    reader.onload = function (progressEvent) {
      const arr = this.result.split(/\r\n|\n/);
      let keyword = "";
      for (let i = 0; i < arr.length; i++) {
        if (unicodeEscape(arr[i]) != "") {
          keyword = keyword + "'" + unicodeEscape(arr[i]) + "',";
        }
      }
      keyword = keyword.slice(0, -1);

      //Tampermonkeyに貼り付けるUserScriptの作成
      let str = "// ==UserScript==\n";
      str += "// @name         RmNgWord\n";
      str += "// @namespace    http://tampermonkey.net/\n";
      str += "// @version      19.20220729113717\n";
      str +=
        "// @description  Remove terms you don't want to see on the Web'.)\n";
      str += "// @match     *://*/*\n";
      // str += "// @include        *\n";
      str += "// ==/UserScript==\n";

      str += "(function() {\n";
      str += "    'use strict';\n";
      str += "const replaceWord = '';\n";
      str += "const ng_words = [" + keyword + "];\n";

      str += "let rmNgWord = function(node){\n";
      str +=
        "let textNodes = document.evaluate('//text()', node, null, 6, null);\n";
      str += "let i, j, lenC, lenNG, txt;\n";
      str += "for (i=0, lenC=textNodes.snapshotLength; i<lenC; i++) {\n";
      str += "txt = textNodes.snapshotItem(i).nodeValue;\n";
      str += "for (j=0, lenNG=ng_words.length; j<lenNG; j++){\n";
      str += "if(txt.indexOf(ng_words[j]) >= 0){\n";
      str += "textNodes.snapshotItem(i).nodeValue = replaceWord;\n";
      str += "break;\n";
      str += "}\n";
      str += "}\n";
      str += "}\n";
      str += "};\n";

      str += "rmNgWord(document);\n";
      str += "})();\n";

      // console.log("str", str);

      let blob = new Blob([str], { type: "text/plan" });
      let link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = "output.js";
      link.click();
    };
    reader.readAsText(file);
  };

  // 文字列をUnicode(\uxxx形式)へエスケープ
  const unicodeEscape = function (str) {
    if (!String.prototype.repeat) {
      String.prototype.repeat = function (digit) {
        let result = "";
        for (let i = 0; i < Number(digit); i++) result += str;
        return result;
      };
    }

    let strs = str.split(""),
      hex,
      result = "";

    for (let i = 0, len = strs.length; i < len; i++) {
      hex = strs[i].charCodeAt(0).toString(16);
      result += "\\u" + "0".repeat(Math.abs(hex.length - 4)) + hex;
    }

    return result;
  };
</script>

3.すると、下記のようなボタンが表示されます。
スクリーンショット 2022-07-31 19.19.35.png

4.このボタンをクリックすると、下記ダイアログが表示されるので、先ほどの除外文字を記載したjogai.txtを選択します。
スクリーンショット 2022-07-31 19.21.35.png

5.すると、下記のようなダイアログが表示されるので、output.jsというユーザースクリプトファイルを出力保存します。
スクリーンショット 2022-07-31 19.22.04.png
このファイルの中身は、下記のとおりです。

出力ファイル

output.js
// ==UserScript==
// @name         RmNgWord
// @namespace    http://tampermonkey.net/
// @version      19.20220729113717
// @description  Remove terms you don't want to see on the Web'.)
// @match     *://*/*
// ==/UserScript==
(function () {
  "use strict";
  const replaceWord = "";
  const ng_words = ["\u30b3\u30ed\u30ca", "\u30ef\u30af\u30c1\u30f3"];
  let rmNgWord = function (node) {
    let textNodes = document.evaluate("//text()", node, null, 6, null);
    let i, j, lenC, lenNG, txt;
    for (i = 0, lenC = textNodes.snapshotLength; i < lenC; i++) {
      txt = textNodes.snapshotItem(i).nodeValue;
      for (j = 0, lenNG = ng_words.length; j < lenNG; j++) {
        if (txt.indexOf(ng_words[j]) >= 0) {
          textNodes.snapshotItem(i).nodeValue = replaceWord;
          break;
        }
      }
    }
  };
  rmNgWord(document);
})();

このファイルをTampermonkeyから読み込むことで、ブラウザに適用され、除外文字列が空白で表示されるようになっています。

Tampermonkeyのコード

remove_ngword
// ==UserScript==
// @name         remove_ngword
// @version      0.1
// @description  
// @author       ike
// @match        *://*/*
// @grant        none
// @require      file:///Users/ike/desktop/jogai/output.js
// ==/UserScript==

ブラウザでの出力例

スクリーンショット 2022-07-31 19.41.39.png

改善したい点

以上のように、現在は、
1.jogai.txtに除外したい文字を入力し、保存
2.index.htmlファイルをブラウザに貼り付け
3.ボタンを押して、jogai.txtファイルを選択
4.output.txtを出力
という手順が必要です。

それを、
1.jogai.txtに除外したい文字を入力し、保存
するだけで、index.html内のscript処理が走って、output.txtの出力まで終わる
ようにしたいです。

なにか良い案があれば、教えていただけましたら幸いです。

0

2Answer

jogai.txtをサーバーに配置して、定期的な更新チェックを入れるくらいですかね。
即反映は仕組み上難しいので、いっそのこと拡張機能を作って
その中でテキストファイルを管理する方が無難かも

1Like

Comments

  1. @ike81818

    Questioner

    なるほど。拡張機能を作るの良さそうですね。作ったことないので、何をすれば良いのかさっぱりわかりませんが。除外キーワードを保存する設定画面みたいなのを作って、そこに保存するとブラウザに反映するような感じですかね。

テキストファイルの代わりにfirestoreを使ってリアルタイムの更新を受け取ればできそうな気もします。

クライアント
Tampermonkey → firestore (onSnapshot) → ブラウザに反映

1Like

Your answer might help someone💌