Chrome 有没有插件可以一键保存当前打开的所有标签页?

1,000 阅读5分钟

说在前面

🎈最近在某乎看到这么一个问题,觉得挺有意思的,想着自己有时候好像也需要用到这样的一个功能,所以便有自己动手做这么一个插件的想法,这里简单分享下这个Chrome插件是怎么快速开发出来的。

实现方案

一、插件框架

vue-chrome-extension-quickstartgitee.com/zheng_yongt…

二、数据存储

通过 gitee 来做存取

建一个私有仓库来保存自己的tab标签信息,需要同步的时候再获取 gitee 仓库的tab标签到本地。这样不用自己写服务端对数据进行存储,不用服务器也可以完成数据存储工作,减少了很多不必要的开发工作。

实现步骤

一、准备工作

1、新建 gitee 仓库

直接在gitee上新建仓库即可。

我们不想要保持的标签信息公开,所以选择勾选上私有: image.png

创建完的初始仓库是这样的: image.png

我们再新增一个目录,用于存放保存的tab标签文件:

二、插件编写

完成前面的准备工作,新建完 gitee 仓库之后,我们便可以正式开始进行插件的编写了。

1、插件模板

  • 安装依赖jyeontu
npm i -g jyeontu
  • 获取模板
jyeontu create

image.png

  • 生成模板

根据提示输入相关信息即可

生成的文件目录如下:

2、giteeAPI

我们可以通过 giteeAPI 来对 gitee 仓库进行操作,下面是 giteeAPI 的操作文档: gitee.com/api/v5/swag…

(1)获取gitee指定文件的内容

我们可以通过下面代码来获取到gitee指定仓库指定文件的内容:

async function fetchFileContent(apiUrl, accessToken) {
  const response = await fetch(apiUrl, {
    headers: {
      Authorization: "token " + accessToken,
    },
  });
  const fileData = await response.json();
  return fileData.content;
}

export async function getFile(gitInfo) {
  const accessToken = gitInfo.token;
  const apiUrl =
    "https://gitee.com/api/v5/repos/" +
    gitInfo.owner +
    "/" +
    gitInfo.repo +
    "/contents/" +
    gitInfo.filePath;

  const fileContent = await fetchFileContent(apiUrl, accessToken);
  const decodedContent = atob(fileContent); // 解码Base64编码的文件内容
  const decoder = new TextDecoder();
  const decodedData = decoder.decode(
    new Uint8Array([...decodedContent].map((char) => char.charCodeAt(0)))
  );
  return JSON.parse(decodedData);
}
(2)修改指定文件的内容数据

我们需要先获取到文件,拿到文件的sha值,后面通过sha来对文件进行编辑操作。 btoa函数只能处理Latin1字符范围内的字符串,对超出Latin1字符范围的字符串进行Base64编码,我们需要进行以下操作,使用TextEncoder对象来将字符串转换为字节数组,然后再进行Base64编码。

async function fetchFileContent(apiUrl, accessToken) {
  const response = await fetch(apiUrl, {
    headers: {
      Authorization: "token " + accessToken,
    },
  });
  const fileData = await response.json();
  return fileData.content;
}
async function getDecodedContent(content) {
  const decodedContent = atob(content); // 解码Base64编码的文件内容
  const decoder = new TextDecoder();
  const decodedData = decoder.decode(
    new Uint8Array([...decodedContent].map((char) => char.charCodeAt(0)))
  );
  return JSON.parse(decodedData);
}
async function putFileContent(apiUrl, accessToken, encodedContent, sha) {
  const commitData = {
    access_token: accessToken,
    content: encodedContent,
    message: "Modified file",
    sha: sha,
  };

  const putResponse = await fetch(apiUrl, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
      Authorization: "token " + accessToken,
    },
    body: JSON.stringify(commitData),
  });

  if (putResponse.ok) {
    console.log("File modified successfully.");
  } else {
    console.error("Failed to modify file.");
  }
}
export async function modifyFile(gitInfo, modifiedContent) {
  const accessToken = gitInfo.token;
  const apiUrl =
    "https://gitee.com/api/v5/repos/" +
    gitInfo.owner +
    "/" +
    gitInfo.repo +
    "/contents/" +
    gitInfo.filePath;

  try {
    const fileContent = await fetchFileContent(apiUrl, accessToken);
    const content = await getDecodedContent(fileContent);
    modifiedContent = mergeBookmarks(content, modifiedContent);
    modifiedContent = JSON.stringify(modifiedContent);
    const encoder = new TextEncoder();
    const data = encoder.encode(modifiedContent);
    const encodedContent = btoa(
      String.fromCharCode.apply(null, new Uint8Array(data))
    );

    await putFileContent(apiUrl, accessToken, encodedContent, fileContent.sha);
  } catch (error) {
    console.error("An error occurred:", error);
  }
}

3、chrome API

(1)获取当前打开的所有tab标签信息
const getChromeTab = (config = {}) => {
  return new Promise((resolve) => {
    chrome.tabs.query(config, function (tab) {
      resolve(tab);
    });
  });
};
(2)在一个窗口打开多个tab标签
chrome.windows.create({ url: urls, type: "normal" });

插件使用

1、插件下载

直接到gitee上下载源码即可:

源码地址:gitee.com/zheng_yongt…

2、导入插件

一键保存浏览器打开的所有标签插件的目录如下:

下载完后打开浏览器扩展程序管理页面(chrome://extensions/),选择加载已解压的扩展程序:

image.png

选择插件目录导入即可:

导入成功后就可以看到下面这个插件了

可以勾选上下面这个,勾选后插件就会显示在导航栏上

3、补充gitee仓库信息数据

导入插件后,我们点击导航栏的插件图标,可以看到这样一个面板,其中有四个数据需要我们填写:

获取 token

进入到giteeAPI文档进行授权获取到返回填写即可,具体步骤如下: image.png

image.png

image.png

image.png

仓库所属空间地址(owner)

就是个人主页的一个空间地址,如下图: image.png

仓库路径(repo)

前面新建仓库的路径(仓库名),如下图: image.png

文件保存目录(filePath)

新建用于保存书签数据的文件,想保存多份不同的数据的话可以多件几个不同的文件分别进行存储,同步的时候选择对应的目录即可,如下图: image.png

将对应信息填写上之后我们就可以开始使用插件了:

  • 切到浏览器标签记录页面

已保存的tab标签记录都会在页面上显示,点击下方保存按钮可以将当前打开的所有tab标签页保存。

  • 一键打开保存的所有窗口标签

  • 一键打开指定窗口所有标签

源码

gitee 地址:gitee.com/zheng_yongt…

觉得有帮助的可以点个star~

有什么问题或错误可以指出,欢迎pr~

有什么想要实现的插件或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。