小白也能看得懂!如何在浏览器插件的文件中合法引入第三方依赖远程代码?

背景介绍

随着Chrome拓展升级到V3版本,谷歌又在慢慢的收紧权限,现在已经不允许在插件中运行远程代码,这也导致了一些问题。比如最近利用浏览器插件,获取页面的数据,然后把关键词做成一个思维导图,生成HTML保存下来,这时候借助了第三方插件jsMind,在生成的HTML页面的时候,通过js拼接代码在页面中嵌入jsMind的依赖,如下所示:

// jsMind 库的 CDN 路径 
const jsMindCSS = '<https://unpkg.com/jsmind@0.8.4/style/jsmind.css>' 
const jsMindJS = '<https://unpkg.com/jsmind@0.8.4/es6/jsmind.js>' 
const jsMindDraggableJS = '<https://unpkg.com/jsmind@0.8.4/es6/jsmind.draggable-node.js>' 
const docToImageJS = '<https://unpkg.com/dom-to-image@2.6.0/dist/dom-to-image.min.js>' 
const screenshotJS = '<https://unpkg.com/jsmind@0.8.4/es6/jsmind.screenshot.js>'

但是Chrome认为这是远程代码,在插件审核的时候给打回了,这就很尴尬,这时候该怎么办呢?

解决思路

如果远程代码不允许的话,那么只能考虑从本地引入的方式,但是这时候还会有一些问题,浏览器中的 Chrome 插件不支持直接访问文件系统,那么这里我直接将所有外部的 JS 和 CSS 资源文件打包到 Chrome 插件的扩展包中,并通过 Chrome 插件的web_accessible_resources配置访问这些资源文件。

1、将资源文件包含在 Chrome 插件中

首先在插件的根目录下创建一个jsmind文件夹,将所有依赖的资源文件(CSS 和 JS 文件)放到插件的 jsmind 目录中

/jsmind/jsmind.css
/jsmind/jsmind.js
/jsmind/jsmind.draggable-node.js
/jsmind/dom-to-image.min.js
/jsmind/jsmind.screenshot.js

2、配置 manifest.json

manifest.json 中配置 web_accessible_resources,确保 HTML 文件生成后能正确访问这些本地资源。

{
  "name": "Mind Map Chrome Plugin",
  "version": "1.0",
  "manifest_version": 3,
  "web_accessible_resources": [
    {
      "resources": [
        "jsmind/jsmind.css",
        "jsmind/jsmind.js",
        "jsmind/jsmind.draggable-node.js",
        "jsmind/dom-to-image.min.js",
        "jsmind/jsmind.screenshot.js"
      ],
      "matches": ["<all_urls>"]
    }
  ]
}

3、动态获取资源的路径

使用 chrome.runtime.getURL()这个 API 可以生成相对路径的 URL,指向 Chrome 插件的本地资源。我们可以通过这个方法引用 CSS 和 JS 文件,而不依赖于外部 CDN。
修改后的获取文件的代码如下所示:

// 相对路径指向插件中的本地资源 
const jsMindCSSUrl = chrome.runtime.getURL('jsmind/jsmind.css'); 
const jsMindJSUrl = chrome.runtime.getURL('jsmind/jsmind.js'); 
const jsMindDraggableJSUrl = chrome.runtime.getURL('jsmind/jsmind.draggable-node.js'); 
const docToImageJSUrl = chrome.runtime.getURL('jsmind/dom-to-image.min.js'); 
const screenshotJSUrl = chrome.runtime.getURL('jsmind/jsmind.screenshot.js');

4、优化代码

这时候会有一个问题,不知道大家有没有关注到:

chrome.runtime.getURL()可以动态获取资源的路径,可以确保生成的 HTML 文件能够正确加载本地资源并离线运行。但是这种方法只有在插件环境中是有效的,生成的文件发送给别人是无法打开的,一旦插件卸载了,或者插件的ID改变了,HTML中的引入路径就失效了

为了解决这个问题,我们可以通过 fetch 或者类似的方法获取资源文件的内容(如 CSS 和 JS 文件),然后将这些内容直接嵌入到生成的 HTML 文件中。这种方式可以确保生成的文件完全独立,可以发送给别人,并且在离线情况下运行。

// 使用 fetch 获取文件内容 
const jsMindCSS = await fetch(jsMindCSSUrl).then(res => res.text()); 
const jsMindJS = await fetch(jsMindJSUrl).then(res => res.text()); 
const jsMindDraggableJS = await fetch(jsMindDraggableJSUrl).then(res => res.text()); 
const docToImageJS = await fetch(docToImageJSUrl).then(res => res.text()); 
const screenshotJS = await fetch(screenshotJSUrl).then(res => res.text());

代码设计思路:

  1. 使用 chrome.runtime.getURL() 动态获取 Chrome 插件中资源的路径。
  2. 使用 fetch() 方法从这些路径读取文件的内容(如 CSS 和 JS 文件)。
  3. 将这些文件内容以 内联 方式嵌入到生成的 HTML 文件中,而不是通过外部链接引用。
  4. 最终生成的 HTML 文件是完全独立的,别人收到文件后也能正常运行。

整体代码:

import { saveAs } from 'file-saver';

// 动态获取资源文件路径
const jsMindCSSUrl = chrome.runtime.getURL('jsmind/jsmind.css');
const jsMindJSUrl = chrome.runtime.getURL('jsmind/jsmind.js');
const jsMindDraggableJSUrl = chrome.runtime.getURL('jsmind/jsmind.draggable-node.js');
const docToImageJSUrl = chrome.runtime.getURL('jsmind/dom-to-image.min.js');
const screenshotJSUrl = chrome.runtime.getURL('jsmind/jsmind.screenshot.js');

// 通过 fetch 读取资源文件内容,并生成 HTML 文件
async function generateMindMap(nodeArray, name) {
  // 使用 fetch 获取文件内容
  const jsMindCSS = await fetch(jsMindCSSUrl).then(res => res.text());
  const jsMindJS = await fetch(jsMindJSUrl).then(res => res.text());
  const jsMindDraggableJS = await fetch(jsMindDraggableJSUrl).then(res => res.text());
  const docToImageJS = await fetch(docToImageJSUrl).then(res => res.text());
  const screenshotJS = await fetch(screenshotJSUrl).then(res => res.text());

  // 生成 HTML 文件内容,内嵌 CSS 和 JS
  const htmlContent = `<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsMind Example</title>
        <style>
          ${jsMindCSS} /* 内联 CSS 内容 */
          #jsmind_container {
            width: 100vw;
            height: 100vh;
          }
        </style>
    </head>
    <body>
        <div id="jsmind_container"></div>
        <button 
        οnclick="takeScreenshot()" 
        style="
            position: fixed; 
            bottom: 10px; 
            right: 20px; 
            background-color: #3498db; 
            border: none; 
            color: white; 
            padding: 10px 20px; 
            text-align: center; 
            text-decoration: none; 
            display: inline-block; 
            font-size: 16px; 
            cursor: pointer; 
            z-index: 1000;">
        导出图片
      </button>
        <script type="text/javascript">
          ${jsMindJS} /* 内联 jsMind 主库 JS */
        </script>
        <script type="text/javascript">
          ${jsMindDraggableJS} /* 内联 jsMind Draggable JS */
        </script>
        <script type="text/javascript">
          ${docToImageJS} /* 内联 dom-to-image JS */
        </script>
        <script type="text/javascript">
          ${screenshotJS} /* 内联 jsMind Screenshot JS */
        </script>
        <script type="text/javascript">
            var mind = {
                "meta": {
                    "name": "可怜的汤姆",
                    "author": "小猫咪",
                    "version": "1.0.0"
                },
                "format": "node_array",
                "data": ${JSON.stringify(nodeArray)}
            };
            var options = {
                container: 'jsmind_container',
                editable: false,
                theme: 'belizehole',
                view:{
                  engine:'svg'
                }
            };
            var jm = new jsMind(options);
            jm.show(mind);
            function takeScreenshot() {
              jm.screenshot.options.background = 'white';
              jm.screenshot.options.filename = '${name}';
              jm.shoot();
            }
        </script>
    </body>
    </html>`;

  // 创建 Blob 对象并保存文件
  const blob = new Blob([htmlContent], { type: 'text/html;charset=utf-8' });
  saveAs(blob, `${name}.html`);
}

export default generateMindMap;

通过上述的代码将所有的 CSS 和 JS 文件内容都被嵌入到了生成的 HTML 文件中,这样生成的 HTML 文件不依赖外部的文件,完全独立。最终生成的 HTML 文件会包含所有的必要资源,不再依赖插件环境,任何人都可以打开该 HTML 文件并查看思维导图,甚至可以离线运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值