简体   繁体   English

如何编写将内容脚本应用于单页应用程序的 chrome 扩展?

[英]How do I write a chrome extension that applies a content script to a Single Page Application?

I'm currently in the process of writing a extension that'll turn every string that matches a RegEx pattern, specifically the RegEx pattern for german telephone numbers, into clickable links by prepending tel: in the href of the element and surrounding it with an anchor tag if needed.我目前正在编写一个扩展程序,该扩展程序会将与 RegEx 模式(特别是德国电话号码的 RegEx 模式)匹配的每个字符串转换为可点击的链接,方法是在元素的 href 中添加 tel: 并用如果需要,锚标记。

For the last three days I've been trying to make it work for this one Single Page App our company uses for their contacts.在过去的三天里,我一直在努力使其适用于我们公司用于联系人的这个单页应用程序。 But whenever I load my extension into the browser and then restart the browser it doesn't apply my content script at first.但是每当我将扩展程序加载到浏览器然后重新启动浏览器时,它首先不会应用我的内容脚本。 I first need to refresh the page after visiting it.我首先需要在访问后刷新页面。

I'm using the following files:我正在使用以下文件:

manifest.json:清单.json:

{
  "name": "testExtension",
  "short_name": "testExtension",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "Replace telephone numbers with clickable links.",
  "author": "Ngelus",
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  "browser_action": {
    "default_icon": "icons/icon48.png",
    "default_title": "testExtension"
  },
  "default_locale": "en",
  "permissions": [
    "tabs",
    "activeTab",
    "<all_urls>",
    "*://*.examplecontactsapp.de/*",
    "storage",
    "webRequest",
    "webNavigation"
  ],
  "content_scripts": [
    {
      "matches": [
        "*://web.examplecontactsapp.de/contacts",
        "*://web.examplecontactsapp.de/contacts*"
      ],
      "js": ["src/inject/contentscript.js"]
    }
  ],
  "background": {
    "scripts": ["src/bg/background.js"],
    "persistent": true
  }
}

background.js:背景.js:

let currentUrl = '';
let tabId;

chrome.webRequest.onCompleted.addListener(
  function (details) {
    const parsedUrl = new URL(details.url);

    if (currentUrl && currentUrl.indexOf(parsedUrl.pathname) > -1 && tabId) {
      chrome.tabs.sendMessage(tabId, { type: "pageRendered" });
    }
  },
  { urls: ['*://web.examplecontactsapp.de/contacts*'] }
);

chrome.webNavigation.onHistoryStateUpdated.addListener(
  (details) => {
    tabId = details.tabId;
    currentUrl = details.url;
  },
  {
    url: [
      {
        hostSuffix: 'examplecontactsapp.de',
      },
    ],
  }
);

contentscript.js:内容脚本.js:

var readyStateCheckInterval = setInterval(function () {
  if (!location.href.startsWith('https://web.examplecontactsapp.de/contacts')) return;
  if (document.readyState === 'complete') {
    clearInterval(readyStateCheckInterval);
    console.log(
      `[---testExtension---]: replacing all telephone numbers with clickable links...`
    );
    replaceNumbersWithLinks();
  }
}, 10);

chrome.runtime.onMessage.addListener(function (request) {
  if (request && request.type === 'pageRendered') {
    const readyStateCheckInterval = setInterval(function () {
      if (document.readyState === 'complete') {
        clearInterval(readyStateCheckInterval);
        console.log(
          `[---testExtension---]: replacing all telephone numbers with clickable links...`
        );
        replaceNumbersWithLinks();
      }
    }, 10);
  }
});

function replaceNumbersWithLinks() {
  document
    .querySelectorAll(
      'body > main > div.page-content > div > table > tbody > tr > td > p > a'
    )
    .forEach((a) => {
      var b = a.innerText.replaceAll(' ', '').trim();
      a.removeAttribute('data-phonenumber');
      if (b != '') a.href = 'tel:' + b;
    });
}

What's the proper way to do this?这样做的正确方法是什么? How do I make it work whenever I visit that single page app?每当我访问该单页应用程序时,如何使其工作?

Thank you all in advance.谢谢大家。

Make matches match the entire site in manifest.json:使matches匹配 manifest.json 中的整个站点:

{
  "content_scripts": [
    {
      "matches": [
        "*://web.examplecontactsapp.de/*"
      ],
      "js": ["src/inject/contentscript.js"]
    }
  ],

Use MutationObserver and check for the selector on each mutation in contentscript.js using querySelector, which is moderately fast, then proceed with the slow querySelectorAll on success:使用 MutationObserver 并使用中等速度的 querySelector 检查 contentscript.js 中每个突变上的选择器,然后在成功时继续执行慢速 querySelectorAll:

const SEL = 'a[data-phonenumber]';
const mo = new MutationObserver(onMutation);
observe();

function onMutation() {
  if (document.querySelector(SEL)) {
    mo.disconnect();
    replaceNumbersWithLinks();
    observe();
  }
}

function observe() {
  mo.observe(document, {
    subtree: true,
    childList: true,
  });
}

function replaceNumbersWithLinks() {
  document.querySelectorAll(SEL).forEach((a) => {
    a.removeAttribute('data-phonenumber');
    const b = a.textContent.replaceAll(' ', '').trim();
    if (b) a.href = 'tel:' + b;
  });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 网站的javascript完成页面构建后,如何运行Chrome扩展程序内容脚本? - How do I run Chrome extension content script after a site's javascript has finished building page? Chrome 扩展程序:如何获取 web 页面以访问我的内容脚本定义的功能? - Chrome Extension: How do I get a web page to access functions defined by my content script? 如何从内容脚本链接到扩展程序中的页面? - How do I link to a page in my extension from a content script? Chrome扩展程序:如何获取内容脚本扩展程序以显示在某些网站上 - Chrome Extension: How do I get me Content Script Extension to show up on select websites 如何将内容脚本变量发送到后台脚本? (Chrome 扩展程序) - How do I send a content script variable to a background script? (Chrome Extension) 如何将 chrome 扩展中的选定文本从后台脚本传递到内容脚本? - how do i pass selected text in chrome extension from background script to content script? 如何使用Chrome扩展程序中的内容脚本将按钮/图像附加到页面? - How do you append a button/image to a page using a content script in a Chrome Extension? 如何将获取的数据从 chrome 扩展后台脚本发送到内容脚本? - How do I send fetched data from chrome extension background script to content script? 页面动态加载Chrome扩展程序内容时如何运行脚本 - How to run script when page loads content dynamically for Chrome Extension 在chrome扩展中,如何使用内容脚本注入一个Vue页面 - In chrome extension, how to use content script to inject a Vue page
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM