インターネットを私たちの下に曲げましょう









長い間インターネットを( 自分自身のために )少しでも良くしたいと思っていたが、 怠lazの時間がないなら、今日はあなたの幸運な日です。 21のステップで、この大切な目標を達成する方法を示します。



無料ボーナス! インターネットに加えて、Google検索も改善しています。 たぶん、Googleはこのアイデアを高く評価し、手と心を提供します(もしそうなら、私はその研究をあきらめます)。

</冗談>



この記事では、レーキレースでの私自身の経験を使用して、Chrome、FireFox、およびMS Edgeブラウザー用のプラグインを作成する方法について説明します。



プラグインを使用すると、ブラウザで表示されるページに独自のJavaScript / CSSを簡単に埋め込むことができます。 すなわち ブラウザ拡張機能API liteバージョンの一種。



春の初めに、「インターネットテクノロジー」をテーマにしたタームペーパーのタスクが与えられました。

提案されたトピックの中で最も簡単なものを選択したように思えました:「最新のブラウザでのユーザーインターフェイスとナビゲーション」。 彼女が数回後悔したことは、残念ながら遅すぎました。



TL; DR



誰かが21のステップすべてについて読みたくない場合は、5つ行うことができます。



プラグインコードはGitHubからダウンロードできます



そしてその後:



  1. Chromeを開く:// Chromeブラウザの拡張機能
  2. [開発者モード]の横にあるチェックボックスをオンにします
  3. 「アンパックされた拡張機能をロード」をクリックして、ソースコードが保存されたディレクトリを選択します。
  4. その後、「CustomActions」プラグインの「オプション」を選択します
  5. オプションフォームで、[デモ構成]および[保存]をクリックします。






それだけです。たとえば、google.comやHabrを開いたり、構成を修正したり、スクリプトを操作したりできます。



次は叙情的な余談のある拡張版です。



英国の科学者の研究を信じている場合、球状のインターネットユーザーは、彼らが彼に捨てたい情報の量から逃げ、5-10のサイトからなる居心地の良いインターネットの世界を作成します。



認めるのは悲しいでしょうが、鏡を見ると、この非常に球状のユーザーを見ました(おばあちゃん、この記事を読んでいるならダイエットパイだけを作ってください、さもなければ私の幾何学は苦しむでしょう)。



しかし、私の9年半のサイトが完璧ではなかったことに気付くのはさらに悲しいことでした。 したがって、コースワークの一環として、(その他のインターネットとともに)それらをより良くすることが決定されました。



ほとんどの場合、これにはJavaScriptで3〜4行、CSSで2〜3行のみを記述する必要がありました。



最初の調査と協議の後、ブラウザメーカーは機能を拡張する手段を通してそのような機会を提供することが明らかになりました。



ウィッシュリストを定義します。



  1. サイトを開くと、このサイトに関連付けられたユーザーJスクリプトが導入されます
  2. カスタムスクリプトは、設定ページで構成されます。
  3. ブラウザのツールバーにボタンを追加して、構成をすばやく呼び出します


参照条件が定義され、コーディングを開始します。



ステップ1



どちらの側を見るかによって、悟りの前にgetstartedを読んだり、青に変わったりします。



ステップ2



プロジェクトの構造を決定します



options.html

options.js



popup.html

popup.js



background.js



manifest.json



icon.png

images

images\icon128.png

images\icon16.png

images\icon48.png







ステップ3



マニフェストを作成します。



 { "name": "CustomActions", "description": "plugin for CustomActions", "version": "1.0", "background" : { "scripts": ["background.js"] }, "icons": { "128": "images/icon128.png", "16": "images/icon16.png", "48": "images/icon48.png" }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "permissions": [ "webRequest", "tabs", "activeTab", "http://*/*", "https://*/*", "storage", "unlimitedStorage", "contextMenus", "<all_urls>" ], "browser_action": { "default_title": "Custom Actions Injection plugin", "default_icon": "icon.png", "default_popup": "popup.html" }, "commands": { "cmd-exec-1": { "suggested_key": { "default": "Ctrl+Q" }, "description": "Custom Action #1" }, "cmd-exec-2": { "suggested_key": { "default": "Ctrl+B" }, "description": "Custom Action #2" }, "cmd-exec-3": { "suggested_key": { "default": "Ctrl+Y" }, "description": "Custom Action #3" } }, "options_page": "options.html", "manifest_version": 2 }
      
      





ステップ4



私はoptions.htmlフォームに取り組んでいます。



前のセッションに参加したのも不思議ではありません。 コース「Web Design 2.0」のknockout.jsの有用な知識



ファイルknockout-3.4.1.jsとknockout.mapping-latest.jsをプロジェクト構造に追加します。



何も動作しません。 掘ります。 助けにはなりません。 群れ。 Chrome拡張機能はノックアウトを好まないことがわかりました。

愛し、マニフェストを更新します。



 "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
      
      





ステップ5



ユーザーインターフェイスを実装しようとして苦労した後、インスピレーションが生まれます。



クロムからすべてを引き出します://設定



私たちは巨人の肩の上に立って、物事は行きました:







ステップ6



データを保存する必要があります。 chrome.storageについて読んだ

chrome.storage.syncとchrome.storage.localを選択することのジレンマ



chrome.storage.syncはより魅力的ですが、厳しい制限があります。



別の洞察-私はテストプロジェクトを持っているので、ローカルはすべてです。

マニフェストを支配して、制限に問題がないようにします。



そして、chrome.storage.local.setを使用して構成を保存します。



  chrome.storage.local.set(items, function () { self.status('Items saved.'); setTimeout(function () { self.status(''); }, 750); });
      
      





ステップ7



保存された構成はbackground.jsでリロードする必要があることを理解していますが、どのように???



うん、甘いカップルchrome.runtime.sendMessage:

  chrome.storage.local.set(items, function () { self.status('Items saved.'); setTimeout(function () { self.status(''); }, 750); chrome.runtime.sendMessage({ command: 'refreshConfig' }); });
      
      





およびchrome.runtime.onMessage:

  chrome.runtime.onMessage.addListener( function (request, sender, sendResponse) { onCommand(request.command); });
      
      





ステップ8



popup.jsを開きます。 閉じます。 もう一度開けます。 そして7回。 何も明確ではありません。



私はただ一人ですか? 待ちに待った朝が来て、 サンプルにつまずいた。目に見えないGoogleワーカーのおかげで。



貴重な知識の瓦rubをかき集めます。 最後に、正しい例を見つけて、魔法の組み合わせACV(Ctrl-A / Ctrl-C / Ctrl-V)を使用します。 13時間後-ジョブは完了しました。



ステップ9



それでは、主要部分であるインターセプトと実装に進みましょう。



インターセプター-chrome.tabs.onUpdated:

 chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { var url = ''; if (changeInfo && changeInfo.url) url = changeInfo.url.toLowerCase(); else if (tab && tab.url) url = tab.url.toLowerCase(); // . . . });
      
      





およびローバー-chrome.tabs.executeScript:

 if (item.sourceType == 'InjectCSS') chrome.tabs.insertCSS(item.output == 'Owner tab' ? tabId : null, { code: item.data }); else chrome.tabs.executeScript(item.output == 'Owner tab' ? tabId : null, { code: item.source });
      
      





すべてが思ったより簡単になりましたが、それでも私が望んでいたよりも長くなりました。



正規表現と呼ばれる新しい素晴らしい世界を発見しました。 難しいことが簡単にできることがわかりました。



ステップ10



すべて準備完了です。 あなたは正直に稼いだ5つに行くことができます...



...それほど速くない。 5つではなく、多数のコメントと改善をもたらしました。



手順11



最も簡単なものから始めましょう。popup.jsで「現在のサイトを追加」機能のサポートを追加します



思ったほど簡単ではありません。popup.jsからoptions.jsにデータを転送する必要があります。



メッセージをキャッチし、拡張ストレージに保存して読み返すのに3時間を費やしましたが、結局、賢い人は丘を登らないで、彼はそれを迂回することにしました。



クエリ文字列は、この悲しみに対する答えです。



手順12



次の機能はより複雑で、コンテキストメニューのサポートを追加します。

例は再び保存されます。 すべてがそれよりも簡単であることが判明しました-chrome.contextMenus.create:

 chrome.contextMenus.create({ id: item.id, contexts: ["page", "frame", "selection"], title: item.name, onclick: function (info, tab) { onCommand(info.menuItemId); } });
      
      





手順13



私は兆候を信じていませんが、それは幸せな一歩ではありませんでした。



ホットキーを使用して通話をサポートする必要があります。



例のようにすべてを行い、マニフェストを修正します:

 "commands": { "cmd-exec-1": { "suggested_key": { "default": "Ctrl+Q" }, "description": "Custom Action #1" } }
      
      





chrome.commands.onCommandを使用します。

 chrome.commands.onCommand.addListener(onCommand);
      
      





動作しません。 2日間と夜と医療介入の後、設定ページを下にスクロールすると、必要な設定への目立たないリンクが見つかりました。





それは犬が埋葬された場所です。 彼女自身のせいだ、彼女はあまりにも多くの例を教えた、ここにリンクがあり、次の画面に走った。



ステップ14



私たちのzavlabには、英語の教師である妻がいます。 インターフェイスの翻訳が必要です。 英語を学ぶ必要があります。



技術が助けになります。 Google翻訳対英語教師-スコア1:0でGoogleの生活を支援!



手順15



私たちは再び5人をフォローしていますが、私の心ではすでに4人に同意しています。



私はリファクタリングという新しい単語を返します(それ以前は、FACToringという単語しか知りませんでした。特にプロジェクトの最初によく言っていました)。



また、追加の要件は、プログラムを使いやすくし、デモ構成とサンプルを作成することです。



Zavlabは、彼の英語の妻に加えて、UX / UI部門の恋人がいるようです。

しかし、google-examplesの良き人々を思い出して、彼女はほとんど抵抗しませんでした。



手順16



リファクタリングは終了しました。 コードの元のバージョンのカバーの下に隠されているバグの数は驚くべきことです。この言葉をよりよく覚えておく必要があります。



ステップ17



lorem ipsumの例を追加します。 誰がこれをアドバイスしましたか? ラテン語の先生?



要件:キーの組み合わせをクリックすると、フォームのフィールドにlorem言語の文章を入力します。



うまくいったようです。



  var loremDemoData = { names: [ { firstName: "Victoria", lastName: "Veit", email: "Victoria.Veit@noreply.ru" }, { firstName: "Gisele", lastName: "Gillard", email: "Gisele.Gillard@noreply.ru" }, { firstName: "Edmund", lastName: "Edelson", email: "Edmund.Edelson@noreply.ru" }, { firstName: "Joey", lastName: "Janelle", email: "Joey.Janelle@noreply.ru" } ], lorem: [ "Orem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet purus condimentum, porta nulla sed, consequat felis. Phasellus quis condimentum odio. Maecenas scelerisque vehicula leo, sit amet tristique tellus molestie sed. Aenean lacus lorem, feugiat semper imperdiet a, vehicula ac orci. Pellentesque ac nisi commodo, pellentesque lorem quis, fringilla tellus. Fusce bibendum erat sit amet libero maximus rutrum. Integer dictum nibh sodales efficitur congue. Mauris nulla libero, hendrerit eget dictum nec, aliquam eu mi. Donec ipsum nisi, bibendum et consequat eu, imperdiet eget nisl. Duis tincidunt nibh et nibh tempor, quis mattis mi vulputate.", "Suspendisse quis eleifend lectus. Sed nec vehicula elit. Praesent ac sollicitudin diam. Nam at venenatis lectus. Fusce condimentum tortor nec augue vestibulum tempus. Nullam faucibus vehicula lorem, et mollis justo dapibus a. Proin sagittis velit in lectus vehicula, id eleifend urna hendrerit. Integer rhoncus dui sed enim sollicitudin, a finibus magna fermentum.", "Fusce at urna vitae magna semper scelerisque id volutpat tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed ut elit nisl. Duis sit amet ante accumsan nibh ultricies pharetra at vitae purus. Donec a felis eget ipsum euismod tempus. Donec elementum vel tortor vel efficitur. Nunc tristique, magna hendrerit sagittis placerat, odio sem commodo ligula, eu aliquam arcu elit sit amet diam. Etiam ultrices vehicula auctor." ], loremShort: [ "Morbi nec sollicitudin augue.", "Suspendisse sagittis fringilla aliquam.", "Curabitur malesuada dolor.", "Praesent quis lacus neque. Duis vitae vehicula felis" ] };
      
      





  function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min; } var name = data.names[getRandomInt(0, data.names.length)]; var hadEmail = false; var t = document.querySelectorAll('input[type=text], textarea'); for (var i = 0, l = t.length; i < l; i++) { var e = t[i]; var ro = e.getAttribute('readonly'); if (e.disabled || ro === '' || ro === 'true' || ro == '1') continue; var loremTxt = data.lorem[getRandomInt(0, data.lorem.length)]; var loremShort = data.loremShort[getRandomInt(0, data.loremShort.length)]; var na = ('' + e.name).toLowerCase(); var ia = ('' + e.id).toLowerCase(); if (na == 'firstname' || ia == 'firstname' || na == 'fname' || ia == 'fname') e.value = name.firstName; else if (na == 'lastname' || ia == 'lastname' || na == 'lname' || ia == 'lname') e.value = name.lastName; else if (!hadEmail && (na.indexOf('email') >= 0 || ia.indexOf('email') >= 0)) { e.value = name.email; hadEmail = true; } else { e.value = (e.tagName == 'TEXTAREA' ? loremTxt : loremShort); } }
      
      





ステップ18



次の例は、サイトhabrahabr.ru用です



要件:サイトを開くとき、構成にリストされているハブおよび企業の記事を非表示にします。 会社に代わって書かれた記事については、独立した著者によって書かれた記事とは明らかに異なるものにしてください。



その過程で、HabrとGiktaymsの存在について学びました。 私はそれらについて前に知っていたでしょう、すべてが少なくとも2倍高速だったでしょう。 ノンストップで読書を3日間過ごしました。 彼女は昨年だけ記事をマスターしましたが、まだたくさんの興味深いことがあります!



次のアポイントメントで、私の心理療法士は私の苦痛についての記事を書くように勧めました。 彼は、これはこのコースでの作業によって引き起こされる心理的トラウマの治療における重要なステップだと言います。



記事の作成を適切な錠剤の摂取に置き換える提案について、彼は拒否しました。 最後に、私は丸薬に同意しましたが、記事を書くという条件で。 座っています。 私は書いています。



記事の方がコードよりも書きやすいことがわかりました。 たぶん、チュクチは読者ではなく、作家ですか?



 { "showCompanies": [ "yandex", "mosigra" ], "hideCompanies": [ "hashflare" ], "hideHubs": [ "lib" ] }
      
      





  function hideParent(el) { if (el.classList && el.classList.contains('post_teaser')) el.style.display = 'none'; else if (el.parentElement) hideParent(el.parentElement); } function sanitizeParent(el) { if (el.classList && el.classList.contains('post_teaser')) { el.querySelectorAll('img').forEach(function (img) { img.style.display = 'none'; }); el.querySelectorAll('.post__body_crop').forEach(function (chld) { chld.style.maxHeight = '4em'; chld.style.overflow = 'hidden'; el.addEventListener('mouseover', function () { chld.style.maxHeight = "inherit"; chl d.querySelectorAll('img').forEach(function (img) { img.style.display = 'block'; }); }, false); el.addEventListener('mouseout', function () { chld.style.maxHeight = "4em"; chld.querySelectorAll('img').forEach(function (img) { img.style.display = 'none'; }); }, false); }); el.querySelectorAll('.post__title a').forEach(function (titl) { titl.style.color = '#707040'; }); } else if (el.parentElement) sanitizeParent(el.parentElement); } document.querySelectorAll('a[href*="https://geektimes.ru/hub/"]').forEach(function (el) { var hub = el.getAttribute('href').replace(/^.*\.ru\/hub\//, '').replace(/\/.*$/, ''); if (data && data.hideHubs && data.hideHubs.indexOf(hub) >= 0) hideParent(el); }); document.querySelectorAll('a[href*="https://geektimes.ru/company/"], a[href*="https://habrahabr.ru/company/"]').forEach(function (el) { var company = el.getAttribute('href').replace(/^.*\.ru\/company\//, '').replace(/\/.*$/, ''); if (data) { if (data.hideCompanies && data.hideCompanies.indexOf(company) >= 0) { hideParent(el); return; } else if (data.showCompanies && data.showCompanies.indexOf(company) >= 0) return; } sanitizeParent(el); });
      
      





ステップ19



インターネットをさまよい、面白いアイデアを見つけ、Google検索の例としてそれを実装することにしました。



たぶん彼はイニシアチブに感謝し、些細なことを選ぶのをやめるでしょう。



機能:Googleを開くと、最も頻繁に使用される単語とサイトのリストを含むツールチップが表示され、すばやく検索できます。



Harbの例に従って、これはいくつかのナンセンスです。



  var googleDemoData = [ { "keywords": "python", "title": "python" }, { "keywords": "javascript", "title": "javascript" }, { "keywords": "php", "title": "php" }, { "keywords": "mysql", "title": "mysql" }, { "keywords": "site:stackoverflow.com", "title": "at stackoverflow.com" }, { "keywords": "site:developer.mozilla.org", "title": "at developer.mozilla.org" }, { "keywords": "site:developer.chrome.com", "title": "at developer.chrome.com" }, { "keywords": "site:habrahabr.ru", "title": "at habrahabr.ru" } ];
      
      





  function ggSetTimeRange() { var elemId = this.getAttribute('data-range'); var timeLimit = document.querySelector('#' + elemId + ' a'); if (timeLimit) timeLimit.click(); } function ggReplaceAndSearch() { var kw = this.getAttribute('data-search'); if (document.location.href.indexOf('chrome-search://') == 0 || document.location.href.indexOf('https://www.google.com/_/chrome/newtab?') == 0) { document.location.href = "https://www.google.com/search?q=" + encodeURIComponent(kw); return; } var inputText = document.querySelector('input[name="q"]'); if (inputText) { setTimeout(function () { var keyword = '' + inputText.value; if (kw.indexOf('site:') >= 0 && keyword.indexOf('site:') >= 0) { keyword = keyword.replace(/ *site:[^ ]+/, ''); } else if (keyword.indexOf(kw) >= 0) return; kw = ' ' + kw; if (kw.indexOf('site:') >= 0) { inputText.value = keyword + ' ' + kw; setTimeout(function () { var btn = document.querySelector('form[action="/search"]'); if (btn) { btn.submit(); } else { btn = document.querySelector('button[name="btnK"]'); if (btn) { btn.click(); } } }, 100); } else { inputText.value = kw + ' ' + keyword; var strLength = ('' + inputText.value).length; inputText.setSelectionRange(strLength, strLength); } }, 200); setTimeout(function () { inputText.focus(); }, 100); }; }; var ggHelper = document.getElementById('ggHelper'); if (!ggHelper) { var helperHtml = '<div id="ggHelper" style="position: fixed; ' + 'box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); ' + 'background-color: #f0f0f0; border-radius: 2px; flex: 1; ' + 'padding: 0.7em 1em 0.3em 1em; right: 1em; top: 12em; width: 13em; height: ' + (data.length + 4) + 'em; ' + 'font-size: 13px;">' + '<ul style="list-style-type: none; margin: 0; padding: 0;">'; data.forEach(function(dataItem ) { helperHtml += '<li style="text-align: left; cursor: pointer;"><a href="javascript: return false;" data-search="' + dataItem.keywords + '" class="gg-keyword">' + dataItem.title + '</a></li>'; }); helperHtml += '<li style="margin: 0.5em;"><hr size="1" style="height: 1px; border-color: #e0e0e0;"></li>'; helperHtml += '<li style="cursor: pointer;">' + '<a href="javascript: return false;" data-range="qdr_w" class="gg-range">week</a> :: ' + '<a href="javascript: return false;" data-range="qdr_m" class="gg-range">month</a> :: ' + '<a href="javascript: return false;" data-range="qdr_y" class="gg-range">year</a> :: ' + '<a href="javascript: return false;" data-range="qdr_" class="gg-range">any</a></li>'; helperHtml += '</ul></div>'; var bodyTag = document.querySelector('body'); if (bodyTag) { var e = document.createElement('div'); e.innerHTML = helperHtml; bodyTag.appendChild(e.firstChild); document.querySelectorAll('#ggHelper .gg-keyword').forEach(function (el) { el.addEventListener('click', ggReplaceAndSearch); }); document.querySelectorAll('#ggHelper .gg-range').forEach(function (el) { el.addEventListener('click', ggSetTimeRange); }); } }
      
      





ステップ20



ハーバーの遺言によると、私はレビュー用のコードを専門家グループに送信しました。 判定-すべてを書き換えます。 泣いてるよもう泣いてる



連絡後、少なくとも6つのバグが見つかりました。 レビューは力です! この言葉を覚えておく必要があります。

コードを見るといい感じになり、そこに書かれていることとその理由を理解し始めました。



ステップ21



すべて準備完了です。



私はトップ5に進み、4つを頼りにしますが、3つには同意します。 これ以上の強さはありません。

3週間の生活が現代の技術との戦いに投げ込まれます。



頑張って!



PS :. 最後に、stackoverflow.comの作成者とユーザーに心から感謝します。



作成前の作品がどのようなものか想像できません。 そして、Webの出現前(TNBの栄光、私はWebの作成後に生まれました)、プログラマーの職業はおそらく最も落ち込んでおり、単位面積あたりの最高レベルの自殺者でした。



今でも、頭上のすべての植生を引き裂きたい場合もあれば、さらに悪い場合もあります。



PPS :. 批判は大歓迎です。 どれでも。



アップデート1 。 彼らは私に4 ++と評価しました。



「StackOverflowでの盗作が多すぎる」という文言から1つのボールを引きましたが、Habréの記事にプラスを追加しました。 2番目のプラスについての質問に、彼は彼の口ひげを不思議に笑います。



アップデート2 。 2つの良いニュース。



最初のもの 。 ネットワーク技術の先生は、「友達と共有」機能を追加すると、試験に自動的に合格すると約束しました。 駐在員のグループがなじみのない言葉を話しました。



私は座って、node.jsを喫煙しています。キャンペーンは喫煙だけでなく、飲酒も開始する必要があります。 ボトルなしでは理解できません。



雲の中へ。 Herokaで必要ですか? いつものように引き渡す方が良いかもしれません-ベビーベッドとアイゼン。 そして、健康はより高価です。



二番目 。 コメントの投票結果に基づいて3つの追加機能を追加した場合、Zavlabは来年為替レートを相殺することを約束しました。



したがって、機能を改善する方法についてアイデアがある場合は、提案、投票してください。 新しいデモ機能、テンプレート、またはUIのトリッキーなものなどを使用できます。



ワイルドなファンタジーを声に出してください。



3番目 。 それがうまくいけば、卒業証書は何かのために何かをするでしょうか?



アップデート3 。 やった! ドルでの最初の給与。 仕事と旅行のプログラムでは、地元のマクドナルド料理で英語を勉強しています。



学んだ最初のイディオム:「芝生の上のマニア」。 夏の終わりまでには流fluentになると思います。



私はドルに60を掛けます。ゼロの数は、地域センターのプログラマーにとって最高のオファーと競合します。 地区センターでは、係数Nを入力する必要があります。



Nは小さくありません。Mを取る必要があります。



専門家のグループは静かに遠くからうらやましいが、到着すると私たちが騒ぎ立てることを示唆している。 彼らはパイプを持ってくることを要求しています。 しかし、21歳でない人にとっては、楽器を販売していないので、どうすればいいのかわかりません。



私はたくさん思います。



たぶん私の料理は料理ですか? 私は祖母を書き、cheburechnyを開け、ダイエットパイを取引します。 そして、無料のマクドナルドのダイエットでは、私は間違いなく非常に球状のユーザーのままです。



アップデート4 。 法的休息の代わりに、私は眠れない夜のプログラミングを2回過ごしました(そして、この2日間の結果、最初の給与をスターバックスに引き下げました)が、それでもプラグインをFireFoxとMS Edgeに変換しました。



FireFoxはほとんど抵抗しませんでした。 GitHubからコードまたは既製のプラグインをダウンロードできます。



ソースからのダウンロードを許可するには、web-extを使用するか、設定を使用する必要があります。







完成したプラグインをダウンロードするには:







そして、MS Edgeはすべての手足に寄りかかって、ほとんど詰まりませんでした。 私は辞めたかったのですが、切望された為替レートの機械はまだ弱点が強みに勝つことを許していませんでした。



ドキュメントからの言葉:Microsoft Edge拡張機能は現在、デフォルトのポリシー制限のみをサポートしています:script-src 'self'; object-src 'self'、オプションの形式でのノックアウトの使用に終止符を打つ。 角度に変換する必要がありました。 また、冒険なしではありません。



しかし、奇跡が起こり、最終的にすべてが起こりました。 コードはGitHubから取得できます。



about:flagsで開発を有効にする必要があります







その後、ローカルで使用するためにダウンロードできます。







StackOverflowに既に感謝していますか? もう一度、この知識の宝庫の前で帽子を脱ぎます。



All Articles