如何开发手机版网站,南皮做网站,中山网站建设 760,php创建网页说在前面 平时大家都是怎么管理自己的浏览器书签数据的呢#xff1f;有没有过公司和家里的电脑浏览器书签不同步的情况#xff1f;有没有过电脑突然坏了但书签数据没有导出#xff0c;导致书签数据丢失了#xff1f;解决这些问题的方法有很多#xff0c;我选择自己写个chr…说在前面 平时大家都是怎么管理自己的浏览器书签数据的呢有没有过公司和家里的电脑浏览器书签不同步的情况有没有过电脑突然坏了但书签数据没有导出导致书签数据丢失了解决这些问题的方法有很多我选择自己写个chrome插件来做书签同步。 实现方案
通过 gitee 来做存取
建一个私有仓库来保存自己的书签目录信息需要同步的时候再获取 gitee 仓库的书签目录到本地。这样不用自己写服务端对数据进行存储减少了很多不必要的开发工作。
实现步骤
一、准备工作
1、新建 gitee 仓库
直接在gitee上新建仓库即可。
我们不想要书签信息公开所以选择勾选上私有
创建完的初始仓库是这样的
我们再新增一个目录用于存放和书签相关的文件
在该目录下新增一个文件用于保存书签导出的数据
二、插件编写
完成前面的准备工作新建完 gitee 仓库之后我们便可以正式开始进行插件的编写了。
1、插件模板
安装依赖jyeontu
npm i -g jyeontu获取模板
jyeontu create生成模板
根据提示输入相关信息即可 2、giteeAPI
我们可以通过 giteeAPI 来对 gitee 仓库进行操作下面是 giteeAPI 的操作文档 https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoStargazers?exno
获取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);
}修改指定文件的内容数据
我们需要先获取到文件拿到文件的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、indexDb存取
我们不希望每次打开都需要去重新填写gitee仓库的相关信息所以这里我们使用indexDb来对gitee仓库的相关信息做一个保存。
export class IndexedDB {constructor(databaseName, storeName) {this.databaseName databaseName;this.storeName storeName;this.db null;}open() {return new Promise((resolve, reject) {const request window.indexedDB.open(this.databaseName);request.onerror () {reject(new Error(Failed to open database));};request.onsuccess () {this.db request.result;resolve();};request.onupgradeneeded (event) {this.db event.target.result;if (!this.db.objectStoreNames.contains(this.storeName)) {this.db.createObjectStore(this.storeName, {keyPath: id,autoIncrement: true,});}};});}createDatabase() {return new Promise((resolve, reject) {const request window.indexedDB.open(this.databaseName);request.onerror () {reject(new Error(Failed to create database));};request.onsuccess () {this.db request.result;this.db.close();resolve();};request.onupgradeneeded (event) {this.db event.target.result;if (!this.db.objectStoreNames.contains(this.storeName)) {this.db.createObjectStore(this.storeName, {keyPath: id,autoIncrement: true,});}this.db.close();resolve();};});}close() {if (this.db) {this.db.close();this.db null;}}add(data) {return new Promise((resolve, reject) {const transaction this.db.transaction(this.storeName, readwrite);const objectStore transaction.objectStore(this.storeName);const request objectStore.add(data);request.onsuccess () {resolve(request.result);};request.onerror () {reject(new Error(Failed to add data));};});}getAll() {return new Promise((resolve, reject) {const transaction this.db.transaction(this.storeName, readonly);const objectStore transaction.objectStore(this.storeName);const request objectStore.getAll();request.onsuccess () {resolve(request.result);};request.onerror () {reject(new Error(Failed to get data));};});}getById(id) {return new Promise((resolve, reject) {const transaction this.db.transaction(this.storeName, readonly);const objectStore transaction.objectStore(this.storeName);const request objectStore.get(id);request.onsuccess () {resolve(request.result);};request.onerror () {reject(new Error(Failed to get data));};});}delete(id) {return new Promise((resolve, reject) {const transaction this.db.transaction(this.storeName, readwrite);const objectStore transaction.objectStore(this.storeName);const request objectStore.delete(id);request.onsuccess () {resolve();};request.onerror () {reject(new Error(Failed to delete data));};});}update(id, newData) {return new Promise((resolve, reject) {const transaction this.db.transaction(this.storeName, readwrite);const objectStore transaction.objectStore(this.storeName);const getRequest objectStore.get(id);getRequest.onsuccess () {const oldData getRequest.result;if (!oldData) {const addRequest objectStore.add({ ...newData, id });addRequest.onsuccess () {resolve({ ...newData, id });};addRequest.onerror () {reject(new Error(Failed to add data));};} else {const mergedData { ...oldData, ...newData };const putRequest objectStore.put(mergedData);putRequest.onsuccess () {resolve(mergedData);};putRequest.onerror () {reject(new Error(Failed to update data));};}};getRequest.onerror () {reject(new Error(Failed to get data));};});}
}4、书签存取
获取chrome书签
要获取 Chrome 浏览器的书签目录我们可以使用 Chrome 浏览器提供的 API——chrome.bookmarks。下面是一个示例代码演示如何使用chrome.bookmarks API 获取 Chrome 浏览器的书签目录
export const getBookmarks () {return new Promise((resolve) {chrome.bookmarks.getTree(function (bookmarkTreeNodes) {resolve(bookmarkTreeNodes);});});
};在上述代码中我们首先使用chrome.bookmarks.getTree()方法获取 Chrome 浏览器的书签目录树。
请注意要使用chrome.bookmarks API你需要在你的 Chrome 插件中声明bookmarks权限。具体来说在插件清单文件manifest.json中添加以下内容
{manifest_version: 2,name: 你的插件名称,version: 1.0,permissions: [bookmarks],background: {scripts: [bg.js]}
}在上述代码中我们在permissions字段中声明了bookmarks权限以便我们可以使用chrome.bookmarks API。同时在background字段中指定了一个后台脚本bg.js以便我们在后台执行上述代码。
删除chrome浏览器书签
导入书签前我们需要先清除一下当前浏览器的书签通过chrome.bookmarks.removeTree可以删除书签节点。
export function removeBookmarks(bookmarkTreeNodes) {// 遍历书签树删除所有的书签function traverseBookmarks(bookmarkNodes) {for (const node of bookmarkNodes) {if (node.children) {traverseBookmarks(node.children);}// 删除书签节点chrome.bookmarks.removeTree(node.id);}}traverseBookmarks(bookmarkTreeNodes);
}导入书签
使用chrome.bookmarks.create来新建书签。
export function importBookmarks(bookmarkTreeNodes) {// 遍历书签树function traverseBookmarks(bookmarkNodes, parentId) {for (const node of bookmarkNodes) {// 如果节点是文件夹if (node.children) {// 创建一个新的文件夹节点chrome.bookmarks.create({parentId: parentId,title: node.title,},function (newFolderNode) {// 递归遍历子节点traverseBookmarks(node.children, newFolderNode.id);});}// 如果节点是书签else {// 创建一个新的书签节点chrome.bookmarks.create({parentId: parentId,title: node.title,url: node.url,});}}}// 从根节点开始遍历书签树traverseBookmarks(bookmarkTreeNodes[0].children, 1);
}插件使用
1、插件下载
直接到gitee上下载源码即可
源码地址https://gitee.com/zheng_yongtao/chrome-plug-in.git
2、导入插件
书签同步插件的目录如下
下载完后打开浏览器扩展程序管理页面chrome://extensions/选择加载已解压的扩展程序 选择插件目录导入即可 导入成功后就可以看到下面这个插件了
可以勾选上下面这个勾选后插件就会显示在导航栏上
3、补充gitee仓库信息数据
导入插件后我们点击导航栏的插件图标可以看到这样一个面板其中有四个数据需要我们填写
获取 token
进入到giteeAPI文档进行授权获取到返回填写即可具体步骤如下 仓库所属空间地址(owner)
就是个人主页的一个空间地址如下图
仓库路径(repo)
前面新建仓库的路径仓库名如下图
书签文件路径(filePath)
新建用于保存书签数据的文件想保存多份不同的数据的话可以多件几个不同的文件分别进行存储同步的时候选择对应的目录即可如下图
将对应信息填写上之后我们就可以开始进行同步操作了
4、同步方式
1覆盖保存
使用当前浏览器书签数据覆盖保存到gitee仓库中。
2合并保存
将当前浏览器书签数据与gitee仓库中的书签数据合并好再进行保存。
3覆盖获取
使用gitee仓库中的书签数据覆盖掉本地的书签数据。
4合并获取
将gitee仓库中的书签数据和本地的书签数据合并后再覆盖掉本地的书签数据。
5合并规则
同一层级并且同名的目录我们会将其子节点合并到同一目录下同一层级下我们会根据 书签名 书签url 对该层级的书签进行去重。
源码
1、gitee
gitee 地址https://gitee.com/zheng_yongtao/chrome-plug-in/tree/master/chrome-bookmarks-manage
2、公众号
关注公众号『前端也能这么有趣』发送 chrome插件即可获取源码。
说在后面 这里是 JYeontu现在是一名前端工程师有空会刷刷算法题平时喜欢打羽毛球 平时也喜欢写些东西既为自己记录 也希望可以对大家有那么一丢丢的帮助写的不好望多多谅解 写错的地方望指出定会认真改进 偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章有兴趣的也可以关注下。在此谢谢大家的支持我们下文再见 。
文章转载自: http://www.morning.qbtkg.cn.gov.cn.qbtkg.cn http://www.morning.swkzk.cn.gov.cn.swkzk.cn http://www.morning.mnqz.cn.gov.cn.mnqz.cn http://www.morning.wyfpc.cn.gov.cn.wyfpc.cn http://www.morning.bpmnz.cn.gov.cn.bpmnz.cn http://www.morning.ggtgl.cn.gov.cn.ggtgl.cn http://www.morning.rzczl.cn.gov.cn.rzczl.cn http://www.morning.duqianw.com.gov.cn.duqianw.com http://www.morning.zbgqt.cn.gov.cn.zbgqt.cn http://www.morning.kjtdy.cn.gov.cn.kjtdy.cn http://www.morning.xblrq.cn.gov.cn.xblrq.cn http://www.morning.fjgwg.cn.gov.cn.fjgwg.cn http://www.morning.bnbtp.cn.gov.cn.bnbtp.cn http://www.morning.rckdq.cn.gov.cn.rckdq.cn http://www.morning.jhkzl.cn.gov.cn.jhkzl.cn http://www.morning.kmbgl.cn.gov.cn.kmbgl.cn http://www.morning.tgfjm.cn.gov.cn.tgfjm.cn http://www.morning.qyqmj.cn.gov.cn.qyqmj.cn http://www.morning.hlyfn.cn.gov.cn.hlyfn.cn http://www.morning.qwbls.cn.gov.cn.qwbls.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.rkxdp.cn.gov.cn.rkxdp.cn http://www.morning.bttph.cn.gov.cn.bttph.cn http://www.morning.rnmdp.cn.gov.cn.rnmdp.cn http://www.morning.sfnr.cn.gov.cn.sfnr.cn http://www.morning.pmdlk.cn.gov.cn.pmdlk.cn http://www.morning.knlyl.cn.gov.cn.knlyl.cn http://www.morning.mtyhk.cn.gov.cn.mtyhk.cn http://www.morning.ylsxk.cn.gov.cn.ylsxk.cn http://www.morning.zfyr.cn.gov.cn.zfyr.cn http://www.morning.qzsmz.cn.gov.cn.qzsmz.cn http://www.morning.thnpj.cn.gov.cn.thnpj.cn http://www.morning.xcfmh.cn.gov.cn.xcfmh.cn http://www.morning.kwjyt.cn.gov.cn.kwjyt.cn http://www.morning.kwz6232.cn.gov.cn.kwz6232.cn http://www.morning.tgfjm.cn.gov.cn.tgfjm.cn http://www.morning.gjssk.cn.gov.cn.gjssk.cn http://www.morning.rddlz.cn.gov.cn.rddlz.cn http://www.morning.ywzqk.cn.gov.cn.ywzqk.cn http://www.morning.ghxzd.cn.gov.cn.ghxzd.cn http://www.morning.knmby.cn.gov.cn.knmby.cn http://www.morning.dbfp.cn.gov.cn.dbfp.cn http://www.morning.rhlhk.cn.gov.cn.rhlhk.cn http://www.morning.mdpcz.cn.gov.cn.mdpcz.cn http://www.morning.jbxmb.cn.gov.cn.jbxmb.cn http://www.morning.hlnys.cn.gov.cn.hlnys.cn http://www.morning.gbgdm.cn.gov.cn.gbgdm.cn http://www.morning.zrgdd.cn.gov.cn.zrgdd.cn http://www.morning.lqpzb.cn.gov.cn.lqpzb.cn http://www.morning.krbjb.cn.gov.cn.krbjb.cn http://www.morning.nsyzm.cn.gov.cn.nsyzm.cn http://www.morning.kfcz.cn.gov.cn.kfcz.cn http://www.morning.mmkrd.cn.gov.cn.mmkrd.cn http://www.morning.qjldz.cn.gov.cn.qjldz.cn http://www.morning.skdhm.cn.gov.cn.skdhm.cn http://www.morning.pudejun.com.gov.cn.pudejun.com http://www.morning.xshkh.cn.gov.cn.xshkh.cn http://www.morning.ktnmg.cn.gov.cn.ktnmg.cn http://www.morning.lzdbb.cn.gov.cn.lzdbb.cn http://www.morning.txtzr.cn.gov.cn.txtzr.cn http://www.morning.lysrt.cn.gov.cn.lysrt.cn http://www.morning.qzpsk.cn.gov.cn.qzpsk.cn http://www.morning.banzou2034.cn.gov.cn.banzou2034.cn http://www.morning.pxrfm.cn.gov.cn.pxrfm.cn http://www.morning.qddtd.cn.gov.cn.qddtd.cn http://www.morning.mjzcp.cn.gov.cn.mjzcp.cn http://www.morning.kjfsd.cn.gov.cn.kjfsd.cn http://www.morning.wkmyt.cn.gov.cn.wkmyt.cn http://www.morning.zttjs.cn.gov.cn.zttjs.cn http://www.morning.xnnpy.cn.gov.cn.xnnpy.cn http://www.morning.zcsch.cn.gov.cn.zcsch.cn http://www.morning.pjtnk.cn.gov.cn.pjtnk.cn http://www.morning.thrgp.cn.gov.cn.thrgp.cn http://www.morning.rknsp.cn.gov.cn.rknsp.cn http://www.morning.kongpie.com.gov.cn.kongpie.com http://www.morning.ljglc.cn.gov.cn.ljglc.cn http://www.morning.zxfr.cn.gov.cn.zxfr.cn http://www.morning.lmctj.cn.gov.cn.lmctj.cn http://www.morning.rwyw.cn.gov.cn.rwyw.cn http://www.morning.fznj.cn.gov.cn.fznj.cn