{ lib, pkgs, }: bookmarks: let indent = level: lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); bookmarkToHTML = indentLevel: bookmark: '' ${indent indentLevel}<DT><A HREF="${ lib.escapeXML bookmark.url }" ADD_DATE="0" LAST_MODIFIED="0">${lib.escapeXML bookmark.name}</A>''; directoryToHTML = indentLevel: directory: '' ${indent indentLevel}<DT>${ if directory.toolbar then ''<H3 PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar'' else "<H3>${lib.escapeXML directory.name}" }</H3> ${indent indentLevel}<DL><p> ${allItemsToHTML (indentLevel + 1) directory.bookmarks} ${indent indentLevel}</p></DL>''; itemToHTMLOrRecurse = indentLevel: item: if item ? "url" then bookmarkToHTML indentLevel item else directoryToHTML indentLevel item; allItemsToHTML = indentLevel: bookmarks: lib.concatStringsSep "\n" (map (itemToHTMLOrRecurse indentLevel) bookmarks); bookmarkEntries = allItemsToHTML 1 bookmarks; in pkgs.writeText "firefox-bookmarks.html" '' <!DOCTYPE NETSCAPE-Bookmark-file-1> <!-- This is an automatically generated file. It will be read and overwritten. DO NOT EDIT! --> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <TITLE>Bookmarks</TITLE> <H1>Bookmarks Menu</H1> <DL><p> <DT><H3 ADD_DATE="0" LAST_MODIFIED="0" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar</H3> <DL><p> ${bookmarkEntries} </DL><p> </p></DL> ''