Hier das komplett überarbeitete Skript.
JavaScript
// export_folder_to_html.uc.js
// Exports folder bookmarks to HTML file
// Item "Export folder to HTML" in the context menu of the folder in “Manage Bookmarks” and Sidebar
(async topic => {
let imp = (m, n = m) => ChromeUtils.importESModule(`resource://gre/modules/${m}.sys.mjs`, {})[n];
let exporter = {
get dps() {
delete this.dps;
return this.dps = imp("DownloadPaths");
},
get exporter() {
delete this.exporter;
return this.exporter = imp("BookmarkHTMLUtils", "BookmarkExporter");
},
async export(popup) {
let win = popup.ownerGlobal, tn = popup.triggerNode;
let node, pu = win.PlacesUtils, bm = pu.bookmarks;
if (tn.nodeName == "treechildren") node = popup._view.selectedNode;
else if (tn.id == "OtherBookmarks")
node = {bookmarkGuid: bm.unfiledGuid, title: tn.getAttribute("label")};
else node = tn._placesNode || popup._view.result.root;
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(win, win.PlacesUIUtils.promptLocalization.formatValueSync("places-bookmarks-export"), fp.modeSave);
fp.appendFilters(fp.filterHTML);
fp.defaultString = (node.title ? this.dps.sanitize(node.title) : "untitled") + ".html";
if (await new Promise(fp.open) == fp.returnCancel) return;
let tree = await pu.promiseBookmarksTree(pu.getConcreteItemGuid(node), {includeItemIds: true});
tree.title = bm.getLocalizedTitle(tree);
let bookmarks = {children: [
{root: "toolbarFolder"},
{root: "unfiledBookmarksFolder"},
{root: "bookmarksMenuFolder", children: [tree], guid: bm.menuGuid}
]};
new this.exporter(bookmarks).exportToFile(fp.file.path);
},
observe(doc) {
let popup = doc.querySelector("menupopup#placesContext");
if (!popup) return;
let menuitem = (doc.createXULElement || doc.createElement).call(doc, "menuitem");
for(let args of Object.entries({
label: "Export folder to HTML",
selection: "folder",
"node-type": "folder",
"selection-type": "single|none",
id: "placesContext_exportFolder"
}))
menuitem.setAttribute(...args);
menuitem.exporter = this;
menuitem.addEventListener('click', () => {
this.export(popup); // Übergibt das Popup-Element als Parameter an die Export-Funktion
});
doc.getElementById("placesContext_openSeparator").before(menuitem);
}
};
Services.obs.addObserver(exporter, topic);
Services.obs.addObserver(function quit(s, t) {
Services.obs.removeObserver(quit, t);
Services.obs.removeObserver(exporter, topic);
}, "quit-application-granted");
})("chrome-document-loaded");
Alles anzeigen
Habe noch einen kleinen Fehler in Zeile 52 beseitigt.
Das Skript ruft aber weiterhin NICHT den Speicherdialog auf!
Es wird folgender Fehler ausgeworfen:
Code
Uncaught (in promise) NS_ERROR_XPC_BAD_CONVERT_JS: Could not convert JavaScript argument arg 0 [nsIFilePicker.init]
export file:///C:/Users/Mira/AppData/Roaming/Mozilla/Firefox/Profiles/Testumgebung/chrome/scripts/##_1.js:25
observe file:///C:/Users/Mira/AppData/Roaming/Mozilla/Firefox/Profiles/Testumgebung/chrome/scripts/##_1.js:59
Deutet darauf hin, dass der erste Parameter von fp.init() nicht den erwarteten Typ hat.
Das bedeutet, dass win, der im aktuellen Code an fp.init(win, ...) übergeben wird, nicht den richtigen Fenstertyp darstellt.
Der nsIFilePicker.init()-Aufruf erwartet ein nsIDOMWindow-Objekt als ersten Parameter, aber in deinem Fall ist win möglicherweise kein gültiges Fensterobjekt, was diesen Fehler verursacht.
Was ich damit anfangen soll, ich weiß es nicht.
Ich habe nicht die geringste Ahnung, was da geändert werden muss.