🗂

初心者がVue3を用いて検索結果の一部を非表示にする拡張機能を作成した話

2023/09/26に公開

どうも、なまけろです。
プログラミング初心者なので内容に間違いがある可能性が非常に高いので参考にする際には気をつけてください。
あと、記事を投稿するのは初めてですが、
この記事を見に来た人の全員は自分が作成した拡張機能の作り方を見に来た人だと思うので、ちゃんとした自己紹介は最後にしたいと思います。

環境

自分はVSCodeとWSL2を用いて拡張機能を作成しています。
あとOSはwindows11なのでそれ以外の方は参考にならないかもです。
この記事を読む方はほとんどの方が環境構築を終わらせていると思うので環境構築の方法は省きます。

まず一言

先に言いますが、拡張機能をVueで作ったのではなく、
拡張機能の一部をVue3を用いて作成しただけです。
具体的には、画像右上のようなUIをVue3を用いて作成しただけです。
機能はTypeScriptを用いて作成しました。(大したコードじゃないから実質JavaScript)
スクリーンショット 2023-09-25 175302.png

(UIがめちゃ手抜きなのは許して(^q^)

拡張機能でVue3を使用するのは比較的簡単(ソース:俺)

まず拡張機能を作成するに当たって最低限必要なものは、
以下の3つを持つディレクトリです。

  1. manifest.json
  2. ファイル名.html
  3. ファイル名.js

この3つ、てかmanifest.jsonとhtmlさえあれば機能がなくても良いのであれば作成できます。

では、ここからVue3を用いて作成する方法を説明していこうと思ったのですが、参考にしたサイトの丸パクリみたいな感じになったのでやっぱり説明するのをやめます。このサイト見れば作り方わかると思います。

機能について

自分はタイトルにも書いてある通りChromeの検索結果の一部を非表示にする拡張機能を作成しました。主に書いたファイルは

  • App.vue
  • content.ts

の2つです。App.vueはこんな感じです(ちゃんと作成したわけじゃないので、本職の方見たら発狂するコードだと思う)

<script setup lang="ts">
import { ref } from "vue";


interface Urls {
  id: number,
  url: string,
};
const urls = ref<Urls[]>([]);
let idNumber: number = 0;
let inputUrl: string = "";

const loadUrls = (): void => {
  chrome.storage.local.get(["url"], (result) => {
    if (result.url) {
      let urlArray = result.url.split(" ");
      for (let i = 0; i < urlArray.length; i++) {
        if (urlArray[i] !== "") {
          urls.value.push({
            id: ++idNumber,
            url: urlArray[i],
          });
        }
      }
    }
  });
}

loadUrls();

const addUrl = (url: string): void => {
  urls.value.push({
    id: ++idNumber,
    url: url,
  });
  inputUrl = "";
};

const sendUrls = (): void => {
  let arrayUrls = urls.value.map(url => url.url).join(" ");
  chrome.storage.local.set({ url: arrayUrls });
};

const removeUrl = (listId: number): void => {
  let arrayNumber: number = urls.value.findIndex((url) => url.id === listId);
  urls.value.splice(arrayNumber, 1);
};
</script>

<template>
  <div>
    <div>Input here some urls you consider unnecessary</div>
    <div>
      <input v-model="inputUrl">
      <button @click="addUrl(inputUrl)">add</button>
    </div>
    <div>
      <button @click="sendUrls()">setUrls</button>
    </div>
    <div v-for="{ url, id } in urls" :key="id" id="listDiv">
      <li>{{ url }}</li>
      <button @click="removeUrl(id)">remove</button>
    </div>
  </div>
</template>

<style scoped>
#listDiv {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>

content.tsはこんな感じ

window.onload = async function () {
  chrome.storage.local.get(["url"], (result) => {
    if (result.url) {
      let removeUrl: [] = result.url.split(" ");
      let allSite = document.querySelectorAll('.g');
      allSite.forEach((site) => {
        let linkElement = (site as HTMLElement).querySelector("a");
        if (linkElement) {
          let url = (linkElement as HTMLAnchorElement).href;
          for (let i = 0; i < removeUrl.length; i++) {
            if (url.startsWith(removeUrl[i])) {
              (site as HTMLElement).style.display = "none";
            }
          }
        }
      });
    }
  });
};

拡張機能を作成するに当たって苦労したことが

  1. vueファイルからcontent.tsにどうやってデータを送るか
  2. どこをDOMで操作すれば特定のサイトを非表示にできるか

の2つです。
1つ目に関してはruntime.onMessageやruntime.sendMessageでデータを送ろうとしていたのですが、非同期関数を扱うのが下手でめちゃ手こずっていました。ただ、拡張機能のchrome.storageAPIを使うことによって簡単に作れることに気がつきました。

2つ目はこのサイトのお陰でわかりました。あやうく一生デベロッパーツールとにらめっこするところだった。

初めてまともな(?)制作物が作れた(^q^)

余談

コードを書いている最中、chromeのnamespaceが存在しない的なエラーが出ました。調べてみたらVSCodeにVueの拡張機能を2ついれていたのですが、その片方が原因でした。同じエラーが出ている人はこのサイトが参考になると思います。

あと、この拡張機能を作成していて参考になったサイトを一部以下に書いておきます。

https://crxjs.dev/vite-plugin/

https://ja.vuejs.org/guide/introduction.html

https://reffect.co.jp/vue/vue3-composition/

https://developer.chrome.com/docs/extensions/mv3/getstarted/

https://microsoft.github.io/PowerBI-JavaScript/interfaces/node_modules_typedoc_node_modules_typescript_lib_lib_dom_d.htmlelement.html

あらためて自己紹介

2023-04に大学生になって初めてコマンドラインというものを知って触ったプログラミング初心者です。それまではHTMLをプログラミング言語だと思い、hタグとpタグしか使ったことがないぐらいプログラミングとは無縁の生活を送っていました。あらためて自己紹介とか書いたけど、特に紹介するようなとこはない薄っぺらい人間なので書くの終わります。わざわざこの記事を見ていただき、ありがとうございます。

Discussion