feat: 实现文件夹和书签的持久排序与拖拽功能
This commit is contained in:
@@ -14,22 +14,58 @@ export function parseNetscapeBookmarkHtml(html) {
|
||||
const bookmarks = [];
|
||||
let folderIdSeq = 1;
|
||||
|
||||
function walkDl(dl, parentFolderId) {
|
||||
const children = Array.from(dl.children);
|
||||
for (const node of children) {
|
||||
if (node.tagName?.toLowerCase() !== "dt") continue;
|
||||
function normText(s) {
|
||||
return String(s || "").replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
const h3 = node.querySelector(":scope > h3");
|
||||
const a = node.querySelector(":scope > a");
|
||||
const nextDl = node.nextElementSibling?.tagName?.toLowerCase() === "dl" ? node.nextElementSibling : null;
|
||||
// Collect <DT> nodes that belong to the current <DL> level.
|
||||
// Chrome/Edge exported HTML often uses `<DL><p>` and browsers may wrap
|
||||
// subsequent nodes under <p> or other wrapper elements.
|
||||
function collectLevelDt(container) {
|
||||
const out = [];
|
||||
const els = Array.from(container.children || []);
|
||||
for (const el of els) {
|
||||
const tag = el.tagName?.toLowerCase();
|
||||
if (!tag) continue;
|
||||
if (tag === "dt") {
|
||||
out.push(el);
|
||||
continue;
|
||||
}
|
||||
if (tag === "dl") {
|
||||
// nested list belongs to the previous <DT>
|
||||
continue;
|
||||
}
|
||||
out.push(...collectLevelDt(el));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Find the nested <DL> that belongs to a <DT>, even if <DT> is wrapped (e.g. inside <p>).
|
||||
function findNextDlForDt(dt, stopDl) {
|
||||
let cur = dt;
|
||||
while (cur && cur !== stopDl) {
|
||||
const next = cur.nextElementSibling;
|
||||
if (next && next.tagName?.toLowerCase() === "dl") return next;
|
||||
cur = cur.parentElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function walkDl(dl, parentFolderId) {
|
||||
const dts = collectLevelDt(dl);
|
||||
for (const node of dts) {
|
||||
const h3 = node.querySelector("h3");
|
||||
const a = node.querySelector("a");
|
||||
const nestedDl = node.querySelector("dl");
|
||||
const nextDl = nestedDl || findNextDlForDt(node, dl);
|
||||
|
||||
if (h3) {
|
||||
const id = String(folderIdSeq++);
|
||||
const name = (h3.textContent || "").trim();
|
||||
const name = normText(h3.textContent || "");
|
||||
folders.push({ id, parentFolderId: parentFolderId ?? null, name });
|
||||
if (nextDl) walkDl(nextDl, id);
|
||||
} else if (a) {
|
||||
const title = (a.textContent || "").trim();
|
||||
const title = normText(a.textContent || "");
|
||||
const url = a.getAttribute("href") || "";
|
||||
bookmarks.push({ parentFolderId: parentFolderId ?? null, title, url });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user