Microsoft edgeの拡張機能を作ってみる

Microsoft Edgeの拡張機能を作成するには、まず基本的な構成ファイル(manifest.json)を準備し、JavaScriptを使用して拡張機能のロジックを記述する必要があります。ここでは、設定ページで指定した文字列を含むURLを検索結果から除外する拡張機能の基本的なアイデアとサンプルコードを提供します。

Step 1: manifest.jsonを作成する

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"manifest_version": 3,
"name": "URL Blocker",
"version": "1.0",
"description": "Block specified URLs from search results",
"permissions": ["storage", "activeTab", "scripting"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
},
"options_page": "options.html",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["*://*.google.com/*", "*://*.bing.com/*", "*://*.yahoo.com/*"],
"js": ["content.js"]
}
]
}
{ "manifest_version": 3, "name": "URL Blocker", "version": "1.0", "description": "Block specified URLs from search results", "permissions": ["storage", "activeTab", "scripting"], "action": { "default_popup": "popup.html", "default_icon": { "16": "images/icon16.png", "48": "images/icon48.png", "128": "images/icon128.png" } }, "options_page": "options.html", "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["*://*.google.com/*", "*://*.bing.com/*", "*://*.yahoo.com/*"], "js": ["content.js"] } ] }
{
  "manifest_version": 3,
  "name": "URL Blocker",
  "version": "1.0",
  "description": "Block specified URLs from search results",
  "permissions": ["storage", "activeTab", "scripting"],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "images/icon16.png",
      "48": "images/icon48.png",
      "128": "images/icon128.png"
    }
  },
  "options_page": "options.html",
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["*://*.google.com/*", "*://*.bing.com/*", "*://*.yahoo.com/*"],
      "js": ["content.js"]
    }
  ]
}

Step 2: content.jsを作成する

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
chrome.storage.sync.get('blockedUrls', function(data) {
const blockedUrls = data.blockedUrls || [];
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.addedNodes.length) {
filterSearchResults();
}
});
});
const config = { childList: true, subtree: true };
observer.observe(document.body, config);
function filterSearchResults() {
// 現在のURLを取得
const currentUrl = window.location.href;
// Google、Bing、YahooのURLに基づいて処理を分岐
if (currentUrl.includes("google.com")) {
blockLinksOnGoogle();
} else if (currentUrl.includes("bing.com")) {
blockLinksOnBing();
} else if (currentUrl.includes("yahoo.com")) {
blockLinksOnYahoo();
}
}
function blockLinksOnGoogle() {
document.querySelectorAll('a').forEach(link => {
blockedUrls.forEach(blockedUrl => {
if (link.href.includes(blockedUrl)) {
let element = link.closest('.g');
if (element) {
element.style.display = 'none';
}
}
});
});
// 要素をすべて選択
var elementsG = document.getElementsByClassName('uVMCKf');
// 取得した要素をループして非表示にする
for (var i = 0; i < elementsG.length; i++) {
elementsG[i].style.display = 'none';
}
}
function blockLinksOnBing() {
document.querySelectorAll('a').forEach(elem => {
elem.querySelectorAll('cite').forEach(link => {
blockedUrls.forEach(blockedUrl => {
if (link.textContent.includes(blockedUrl)) {
elem.style.display = 'none';
}
});
});
});
}
function blockLinksOnYahoo() {
// Yahoo検索結果に対する処理(必要に応じて追加)
}
// 初期ロード時にもフィルターを適用
filterSearchResults();
});
chrome.storage.sync.get('blockedUrls', function(data) { const blockedUrls = data.blockedUrls || []; const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.addedNodes.length) { filterSearchResults(); } }); }); const config = { childList: true, subtree: true }; observer.observe(document.body, config); function filterSearchResults() { // 現在のURLを取得 const currentUrl = window.location.href; // Google、Bing、YahooのURLに基づいて処理を分岐 if (currentUrl.includes("google.com")) { blockLinksOnGoogle(); } else if (currentUrl.includes("bing.com")) { blockLinksOnBing(); } else if (currentUrl.includes("yahoo.com")) { blockLinksOnYahoo(); } } function blockLinksOnGoogle() { document.querySelectorAll('a').forEach(link => { blockedUrls.forEach(blockedUrl => { if (link.href.includes(blockedUrl)) { let element = link.closest('.g'); if (element) { element.style.display = 'none'; } } }); }); // 要素をすべて選択 var elementsG = document.getElementsByClassName('uVMCKf'); // 取得した要素をループして非表示にする for (var i = 0; i < elementsG.length; i++) { elementsG[i].style.display = 'none'; } } function blockLinksOnBing() { document.querySelectorAll('a').forEach(elem => { elem.querySelectorAll('cite').forEach(link => { blockedUrls.forEach(blockedUrl => { if (link.textContent.includes(blockedUrl)) { elem.style.display = 'none'; } }); }); }); } function blockLinksOnYahoo() { // Yahoo検索結果に対する処理(必要に応じて追加) } // 初期ロード時にもフィルターを適用 filterSearchResults(); });
chrome.storage.sync.get('blockedUrls', function(data) {
    const blockedUrls = data.blockedUrls || [];

    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.addedNodes.length) {
                filterSearchResults();
            }
        });
    });

    const config = { childList: true, subtree: true };
    observer.observe(document.body, config);
    
    function filterSearchResults() {
        // 現在のURLを取得
        const currentUrl = window.location.href;

        // Google、Bing、YahooのURLに基づいて処理を分岐
        if (currentUrl.includes("google.com")) {
            blockLinksOnGoogle();
        } else if (currentUrl.includes("bing.com")) {
            blockLinksOnBing();
        } else if (currentUrl.includes("yahoo.com")) {
            blockLinksOnYahoo();
        }
    }

    function blockLinksOnGoogle() {
        document.querySelectorAll('a').forEach(link => {
            blockedUrls.forEach(blockedUrl => {
                if (link.href.includes(blockedUrl)) {
                    let element = link.closest('.g');
                    if (element) {
                        element.style.display = 'none';
                    }
                }
            });
        });
        // 要素をすべて選択
        var elementsG = document.getElementsByClassName('uVMCKf');
        // 取得した要素をループして非表示にする
        for (var i = 0; i < elementsG.length; i++) {
            elementsG[i].style.display = 'none';
        }
    }
    
    function blockLinksOnBing() {
        document.querySelectorAll('a').forEach(elem => {
            elem.querySelectorAll('cite').forEach(link => {
                blockedUrls.forEach(blockedUrl => {
                    if (link.textContent.includes(blockedUrl)) {
                        elem.style.display = 'none';
                    }
                });
            });
        });
    }

    function blockLinksOnYahoo() {
        // Yahoo検索結果に対する処理(必要に応じて追加)
    }

    // 初期ロード時にもフィルターを適用
    filterSearchResults();
});

上記のコードでは、Googleの検索結果を対象としていますが、他の検索エンジンについては、適切なセレクターに変更する必要があります。

Step 3: background.jsの作成(オプション)

拡張機能のバックグラウンドスクリプトです。この例では特に必要な機能は実装していませんが、将来的な機能拡張や設定の保存などに利用できます。

Step 4: アイコンとポップアップ(オプション)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html>
<head>
<title>拡張機能のポップアップ</title>
</head>
<body>
<h1>URL Blocker</h1>
<p>オプションページでURLを設定してください。</p>
</body>
</html>
<!DOCTYPE html> <html> <head> <title>拡張機能のポップアップ</title> </head> <body> <h1>URL Blocker</h1> <p>オプションページでURLを設定してください。</p> </body> </html>
<!DOCTYPE html>
<html>
<head>
  <title>拡張機能のポップアップ</title>
</head>
<body>
  <h1>URL Blocker</h1>
  <p>オプションページでURLを設定してください。</p>
</body>
</html>

拡張機能のアイコン(icon.png)とポップアップ用のHTML(popup.html)を追加します。これらはユーザーが拡張機能を操作するためのUIを提供します。

Step 4: 設定ページを作成(オプション)

今回は設定ページにCSVファイルを読み込ませてデータを追加、もしくは手動でデータを追加し、設定ページのローカルストレージにデータを保存する仕組みを作成しました。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html>
<head>
<title>拡張機能の設定</title>
</head>
<body>
<h1>設定</h1>
<input type="file" id="fileInput" accept=".csv">
<button id="importCsv">CSVからインポート</button>
<form id="urlForm">
<input type="text" id="newUrl" placeholder="URLを追加">
<button type="submit">追加</button>
</form>
<table id="urlTable">
<thead>
<tr>
<th>URL</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- URLリストがここに表示される -->
</tbody>
</table>
<button id="exportCsv">CSVでエクスポート</button>
<script src="options.js"></script>
</body>
</html>
<!DOCTYPE html> <html> <head> <title>拡張機能の設定</title> </head> <body> <h1>設定</h1> <input type="file" id="fileInput" accept=".csv"> <button id="importCsv">CSVからインポート</button> <form id="urlForm"> <input type="text" id="newUrl" placeholder="URLを追加"> <button type="submit">追加</button> </form> <table id="urlTable"> <thead> <tr> <th>URL</th> <th>操作</th> </tr> </thead> <tbody> <!-- URLリストがここに表示される --> </tbody> </table> <button id="exportCsv">CSVでエクスポート</button> <script src="options.js"></script> </body> </html>
<!DOCTYPE html>
<html>
<head>
    <title>拡張機能の設定</title>
</head>
<body>
    <h1>設定</h1>
    <input type="file" id="fileInput" accept=".csv">
    <button id="importCsv">CSVからインポート</button>

    <form id="urlForm">
        <input type="text" id="newUrl" placeholder="URLを追加">
        <button type="submit">追加</button>
    </form>
    <table id="urlTable">
        <thead>
            <tr>
                <th>URL</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <!-- URLリストがここに表示される -->
        </tbody>
    </table>
    
    <button id="exportCsv">CSVでエクスポート</button>
    <script src="options.js"></script>
</body>
</html>
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
document.getElementById('urlForm').addEventListener('submit', function(e) {
e.preventDefault();
var newUrl = document.getElementById('newUrl').value;
if (newUrl) {
addUrlToTable(newUrl);
saveUrls();
}
});
function addUrlToTable(url) {
var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0];
var row = table.insertRow();
var urlCell = row.insertCell(0);
var deleteCell = row.insertCell(1);
urlCell.textContent = url;
var deleteButton = document.createElement('button');
deleteButton.textContent = '削除';
deleteButton.addEventListener('click', function() {
row.remove();
saveUrls();
});
deleteCell.appendChild(deleteButton);
}
function saveUrls() {
var urls = [];
var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0];
Array.from(table.rows).forEach(row => {
urls.push(row.cells[0].textContent);
});
chrome.storage.sync.set({ 'blockedUrls': urls });
}
// ページロード時に保存されたURLをテーブルに表示
document.addEventListener('DOMContentLoaded', function() {
chrome.storage.sync.get('blockedUrls', function(data) {
if (data.blockedUrls) {
data.blockedUrls.forEach(url => addUrlToTable(url));
}
});
});
// options.js
document.getElementById('exportCsv').addEventListener('click', function() {
// ストレージからデータを取得
chrome.storage.sync.get('blockedUrls', function(data) {
const blockedUrls = data.blockedUrls || [];
// CSV形式に変換
let csvContent = "data:text/csv;charset=utf-8,";
blockedUrls.forEach(function(row) {
csvContent += row + "\r\n";
});
// Blobを作成し、ダウンロードリンクを生成
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "blocked_urls.csv");
document.body.appendChild(link); // Firefoxで動作するために必要
// リンクをクリックしてダウンロード
link.click();
document.body.removeChild(link); // リンクを削除
});
});
// options.js
document.getElementById('importCsv').addEventListener('click', function() {
var fileInput = document.getElementById('fileInput');
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var text = e.target.result;
var rows = text.split("\n");
var urls = rows.map(function(row) {
return row.trim();
});
// 空の行を削除
urls = urls.filter(function(url) {
return url.length > 0;
});
// ストレージに保存
chrome.storage.sync.set({ 'blockedUrls': urls }, function() {
console.log('URLs are imported!');
// データが保存された後、ページをリロードする
window.location.reload();
});
};
reader.readAsText(file);
});
document.getElementById('urlForm').addEventListener('submit', function(e) { e.preventDefault(); var newUrl = document.getElementById('newUrl').value; if (newUrl) { addUrlToTable(newUrl); saveUrls(); } }); function addUrlToTable(url) { var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0]; var row = table.insertRow(); var urlCell = row.insertCell(0); var deleteCell = row.insertCell(1); urlCell.textContent = url; var deleteButton = document.createElement('button'); deleteButton.textContent = '削除'; deleteButton.addEventListener('click', function() { row.remove(); saveUrls(); }); deleteCell.appendChild(deleteButton); } function saveUrls() { var urls = []; var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0]; Array.from(table.rows).forEach(row => { urls.push(row.cells[0].textContent); }); chrome.storage.sync.set({ 'blockedUrls': urls }); } // ページロード時に保存されたURLをテーブルに表示 document.addEventListener('DOMContentLoaded', function() { chrome.storage.sync.get('blockedUrls', function(data) { if (data.blockedUrls) { data.blockedUrls.forEach(url => addUrlToTable(url)); } }); }); // options.js document.getElementById('exportCsv').addEventListener('click', function() { // ストレージからデータを取得 chrome.storage.sync.get('blockedUrls', function(data) { const blockedUrls = data.blockedUrls || []; // CSV形式に変換 let csvContent = "data:text/csv;charset=utf-8,"; blockedUrls.forEach(function(row) { csvContent += row + "\r\n"; }); // Blobを作成し、ダウンロードリンクを生成 var encodedUri = encodeURI(csvContent); var link = document.createElement("a"); link.setAttribute("href", encodedUri); link.setAttribute("download", "blocked_urls.csv"); document.body.appendChild(link); // Firefoxで動作するために必要 // リンクをクリックしてダウンロード link.click(); document.body.removeChild(link); // リンクを削除 }); }); // options.js document.getElementById('importCsv').addEventListener('click', function() { var fileInput = document.getElementById('fileInput'); var file = fileInput.files[0]; var reader = new FileReader(); reader.onload = function(e) { var text = e.target.result; var rows = text.split("\n"); var urls = rows.map(function(row) { return row.trim(); }); // 空の行を削除 urls = urls.filter(function(url) { return url.length > 0; }); // ストレージに保存 chrome.storage.sync.set({ 'blockedUrls': urls }, function() { console.log('URLs are imported!'); // データが保存された後、ページをリロードする window.location.reload(); }); }; reader.readAsText(file); });
document.getElementById('urlForm').addEventListener('submit', function(e) {
    e.preventDefault();
    var newUrl = document.getElementById('newUrl').value;
    if (newUrl) {
        addUrlToTable(newUrl);
        saveUrls();
    }
});

function addUrlToTable(url) {
    var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0];
    var row = table.insertRow();
    var urlCell = row.insertCell(0);
    var deleteCell = row.insertCell(1);

    urlCell.textContent = url;
    var deleteButton = document.createElement('button');
    deleteButton.textContent = '削除';
    deleteButton.addEventListener('click', function() {
        row.remove();
        saveUrls();
    });
    deleteCell.appendChild(deleteButton);
}

function saveUrls() {
    var urls = [];
    var table = document.getElementById('urlTable').getElementsByTagName('tbody')[0];
    Array.from(table.rows).forEach(row => {
        urls.push(row.cells[0].textContent);
    });
    chrome.storage.sync.set({ 'blockedUrls': urls });
}

// ページロード時に保存されたURLをテーブルに表示
document.addEventListener('DOMContentLoaded', function() {
    chrome.storage.sync.get('blockedUrls', function(data) {
        if (data.blockedUrls) {
            data.blockedUrls.forEach(url => addUrlToTable(url));
        }
    });
});

// options.js

document.getElementById('exportCsv').addEventListener('click', function() {
    // ストレージからデータを取得
    chrome.storage.sync.get('blockedUrls', function(data) {
        const blockedUrls = data.blockedUrls || [];

        // CSV形式に変換
        let csvContent = "data:text/csv;charset=utf-8,";
        blockedUrls.forEach(function(row) {
            csvContent += row + "\r\n";
        });

        // Blobを作成し、ダウンロードリンクを生成
        var encodedUri = encodeURI(csvContent);
        var link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "blocked_urls.csv");
        document.body.appendChild(link); // Firefoxで動作するために必要

        // リンクをクリックしてダウンロード
        link.click();
        document.body.removeChild(link); // リンクを削除
    });
});

// options.js

document.getElementById('importCsv').addEventListener('click', function() {
    var fileInput = document.getElementById('fileInput');
    var file = fileInput.files[0];
    var reader = new FileReader();

    reader.onload = function(e) {
        var text = e.target.result;
        var rows = text.split("\n");

        var urls = rows.map(function(row) {
            return row.trim();
        });

        // 空の行を削除
        urls = urls.filter(function(url) {
            return url.length > 0;
        });

        // ストレージに保存
        chrome.storage.sync.set({ 'blockedUrls': urls }, function() {
            console.log('URLs are imported!');
            // データが保存された後、ページをリロードする
            window.location.reload();
        });
    };

    reader.readAsText(file);
});

Step 5: 拡張機能のテスト

  • Edgeブラウザでedge://extensions/にアクセスします。
  • 右上の「デベロッパーモード」を有効にします。
  • 「展開してパッケージ化されていない拡張機能を読み込む」をクリックし、拡張機能のフォルダを選択します。

これで、指定した条件に基づいて検索結果が除外されるはずです。検索結果の構造は検索エンジンによって異なるため、各検索エンジンのDOM構造に合わせてcontent.jsのセレクターを調整する必要があります。

スポンサーリンク

-IT関連
-

S