重构:提交全新项目代码

This commit is contained in:
2026-05-04 00:04:03 +08:00
commit bca6c31df7
100 changed files with 5524 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>我的自定义书签</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
background: #f5f5f5;
}
#bookmark-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 20px;
}
.bookmark-item {
display: block;
width: 120px;
padding: 15px;
background: white;
border-radius: 8px;
text-decoration: none;
color: #333;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
text-align: center;
}
.bookmark-item:hover {
background: #e0e0e0;
}
</style>
</head>
<body>
<h2>我的书签管理器</h2>
<!-- 文件夹切换下拉框 -->
<select id="folder-selector">
<option value="1">书签栏 (ID: 1)</option>
<!-- 其他文件夹可以通过代码动态加载到这里 -->
</select>
<!-- 书签渲染容器 -->
<div id="bookmark-container"></div>
<script src="popup.js"></script>
</body>
</html>

View File

@@ -0,0 +1,76 @@
// 递归提取某个节点下的所有书签 URL防止文件夹嵌套
function extractUrls(
bookmarkNode: chrome.bookmarks.BookmarkTreeNode[],
): string[] {
let urls: string[] = [];
for (const node of bookmarkNode) {
if (node.url) {
urls.push(node.url);
} else if (node.children) {
urls = urls.concat(extractUrls(node.children));
}
}
return urls;
}
// 渲染指定 ID 文件夹下的书签
async function renderBookmarksByFolderId(folderId: string) {
try {
const results = await chrome.bookmarks.getSubTree(folderId);
const folderNode = results[0];
if (!folderNode || !folderNode.children) return;
const container = document.getElementById("bookmark-container");
if (container) container.innerHTML = "";
// 遍历直接子节点
folderNode.children.forEach((bookmark) => {
if (bookmark.url) {
const link = document.createElement("a");
link.className = "bookmark-item";
link.href = bookmark.url;
link.textContent = bookmark.title || bookmark.url;
// 自动获取网站 favicon 图标
const faviconUrl = `https://www.google.com/s2/favicons?domain=${new URL(bookmark.url).hostname}&sz=32`;
link.innerHTML = `<img src="${faviconUrl}" style="vertical-align: middle; margin-right: 5px;">${bookmark.title}`;
container?.appendChild(link);
}
});
} catch (error) {
console.error("获取书签失败:", error);
}
}
// 初始化:自动获取所有一级文件夹并填充到下拉框
async function initFolderSelector() {
const results = await chrome.bookmarks.getTree();
const bookmarkBar = results[0].children?.[0]; // ID为1的书签栏
const selector = document.getElementById(
"folder-selector",
) as HTMLSelectElement;
if (bookmarkBar && bookmarkBar.children) {
bookmarkBar.children.forEach((folder) => {
// 只把文件夹加到下拉框里
if (!folder.url && folder.id !== "1") {
const option = document.createElement("option");
option.value = folder.id || "";
option.textContent = folder.title || "未命名文件夹";
selector.appendChild(option);
}
});
}
// 绑定切换事件
selector.addEventListener("change", (e) => {
const targetId = (e.target as HTMLSelectElement).value;
renderBookmarksByFolderId(targetId);
});
// 默认渲染书签栏
renderBookmarksByFolderId("1");
}
// 页面加载完成后启动
document.addEventListener("DOMContentLoaded", initFolderSelector);