見出し画像

【拡張機能】デッキ解説記事の作成をサポートする拡張機能を作成しました

タイトルの通りです。
遊戯王公式DBのデッキページで、採用されているカードを抽出する拡張機能を作成しました。
Webストアから拡張機能をインストールすれば使用可能になります。

デッキ解説記事を作成するときに、テラ・フォーミングのようにカード内容をコピーしてくる作業が手間だったので実装しました。
noteでの作業を想定しています。

概要

デッキ画面で拡張機能を開くと、採用カードがボタンで並ぶポップアップウインドウが表示されます。

ボタンを押すと、以下のような装飾済みリンクがクリップボードにコピーされます。

テラ・フォーミング

具体的な使い方

拡張機能の仕様上、別タブに移動した際にポップアップが閉じてしまいます。
デッキ画面を最小幅で別ウインドウで開き、絵を描くときのパレットのように横において使用してください。

仕組み

デッキ内容の抽出は愚直にDOMを取得し、ポップアップウインドウに渡しています。

popup.js

document.addEventListener("DOMContentLoaded", function () {
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    var url = new URL(tabs[0].url);
    if (url.host === "www.db.yugioh-card.com" && url.pathname === "/yugiohdb/member_deck.action" && url.search.startsWith("?ope=1")) {
      // 特定のURLの場合のみロジックを実行
      chrome.tabs.sendMessage(tabs[0].id, { action: "extractDOM" });
    }
  });
});

chrome.runtime.onMessage.addListener(handleExtractedData);

function handleExtractedData(request) {
  if (request.action === "sendExtractedData") {
    updateBody(request.data);
  }
}

function updateBody(extractedData) {
  extractedData.forEach(item => document.body.appendChild(createCopyButton(item.text, item.link)));
}

function createCopyButton(text, link) {
  var copyButton = document.createElement('button');
  copyButton.textContent = text;
  copyButton.className = 'card_button';
  copyButton.addEventListener('click', clickCopyHandler(text, link));
  return copyButton;
}

// クロージャ
function clickCopyHandler(text, link) {
  return function () {
    copyToClipboard(text, link);
  };
}

function copyToClipboard(text, link) {
  var boldText = `<strong>《</strong><a href="${link}" target="_blank" rel="noopener noreferrer nofollow"><strong>${text}</strong></a><strong>》</strong>`;
  const type = 'text/html';
  const blob = new Blob([boldText], { type });
  const data = [new ClipboardItem({ [type]: blob })];
  navigator.clipboard.write(data);
}

content.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.action === "extractDOM") {
      var domContents = [
          ...document.getElementById("detailtext_main").getElementsByClassName("t_row c_normal"),
          ...document.getElementById("detailtext_ext").getElementsByClassName("t_row c_normal")
      ];

      var extractedData = extractDataFromDom(domContents);

      chrome.runtime.sendMessage({ action: "sendExtractedData", data: extractedData });
  }
});

function extractDataFromDom(domContents) {
  var extractedData = [];

  for (var i = 0; i < domContents.length; i++) {
      var childElementName = domContents[i].getElementsByClassName("card_name")[0];
      var childElementLink = domContents[i].getElementsByClassName("link_value")[0].value;

      if (childElementName) {
          var text = childElementName.textContent || childElementName.innerText;

          extractedData.push({
              text: text,
              link: "https://www.db.yugioh-card.com/" + childElementLink
          });
      }
  }

  return extractedData;
}

ボタンを押してコピペさせるためにクリップボード APIを使用しています。

コピー部分のコードは以下です。
HTMLとしてコピペするため、太字でリンク付きのままコピーができるという仕組みです。

function copyToClipboard(text, link) {
  var boldText = `<strong>《</strong><a href="${link}" target="_blank" rel="noopener noreferrer nofollow"><strong>${text}</strong></a><strong>》</strong>`;
  const type = 'text/html';
  const blob = new Blob([boldText], { type });
  const data = [new ClipboardItem({ [type]: blob })];
  navigator.clipboard.write(data);
}

コピーされた時の装飾を変えたい場合、boldText変数を修正してください。

以上となります!
コピペの手間を削減して、デッキ解説に集中できるようになれば嬉しいです。


この記事が気に入ったらサポートをしてみませんか?