Firefox: import HTML bookmark file in a declarative manner

I have an HTML file containing hundreds of bookmarks. I would avoid to insert one by one of them inside my .nix file because too heavy.

How can I import HTML bookmark file for Firefox in a declarative manner inside my .nix file?

1 Like

I’ve written a script that does what you want. I’m currently working on packaging it, but I’m new the the process so it might take a while. If you want to use it, it’s here, but you’ll need to deal with importing the NetscapeBookmarksFileParser yourself. Also, it currently takes input from a directory rather than the terminal as I plan for it to latter.

Interesting. When I finish to code some Nix stuff, Im very interested to test it. Meanwhile I inform some Nix users about it. Thanks!

Hey, @ReedClanton, if you need any help with packaging this, I can help.
Also, could you share your derivation? Even if not finished. I want to test some things on my side. Thanks!

1 Like

I’m happy to share my derivation! You’re going to need to let me know how, or send me a guide, because I only kinda know what a derivation is and defiantly don’t know how to share one.

I don’t know if this would work for you, but I just updated the shell.nix as well as the README.md in the repo to make using the script on a nix system relatively easy. I recommend taking at look at the repo’s README.md if your interested in running it on your own system.

Edit: Also, I’d love help with packaging. I’m currently reading through the nixpkgs README.md in an effort to become antiquated with the process (don’t have any experience with packaging).

@ReedClanton I said derivation but I was talking about your nix expression for the package* sorry!
Don’t hesitate to ask if you have any questions, I can answer those here, or on other platforms (Matrix or Discord) if you’d like to. Thanks for sharing, I’ll take a look and convert some stuff :slight_smile:

I think your asking for the value of programs.firefox.profiles.<name>.bookmarks. If so here’s the link to my entire firefox.nix Home Manager file that sets up the instance of Firefox I’m currently using.

I’ve never liked the idea of installing Discord, but I would like to connect, so I’ll check out Matrix.

I was talking about the packaging part, but no rush, I think we misunderstood each-other.
I don’t know if I did something wrong, but upon running the script, I get this error:

[nix-shell:~/Documents/html2nix]$ nix-shell
Sourcing python-remove-tests-dir-hook
Sourcing python-catch-conflicts-hook.sh
Sourcing python-remove-bin-bytecode-hook.sh
Sourcing pypa-build-hook
Using pypaBuildPhase
Sourcing pypa-install-hook
Using pypaInstallPhase
Sourcing python-imports-check-hook.sh
Using pythonImportsCheckPhase
Sourcing python-namespaces-hook
Sourcing python-catch-conflicts-hook.sh
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/nixos/Documents/html2nix/html2nix.py", line 154, in <module>
    print(html2nix())
          ^^^^^^^^^^
  File "/home/nixos/Documents/html2nix/html2nix.py", line 18, in html2nix
    bookmarks = NetscapeBookmarksFile(file).parse()
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/x2i1qia0jcxdgkms169g9bh5rh4cyxc2-python3.11-NetscapeBookmarksFileParser-1.1/lib/python3.11/site-packages/NetscapeBookmarksFileParser/parser.py", line 228, in parse
    while '<' not in lines[line_num]:
                     ~~~~~^^^^^^^^^^
IndexError: list index out of range

PS: I’ll send you my matrix if you wish, as soon as I get to my laptop.

That error is thrown in the library I use to read in the html files and convert them to objects. Based on the call from my code, I’m sure it’s going to be an issue in the library. The one who created the library has abandoned it, I think, but I’ve made a fork of it so I can trouble shoot the bug and fix it. I won’t be able to do that tonight, but when I do, I’ll need the input that caused the bug (just make sure you remove private data if any).

Hi! Not sure if you’ve seen it already but Firefox has the ability to import bookmarks from an HTML file that you specify in a user pref. If you set browser.places.importBookmarksHTML to true and browser.bookmarks.file to a file path, then Firefox will load bookmarks contained in that file upon starting.

You can configure those prefs with programs.firefox.preferences or programs.firefox.profiles.<name>.settings in Home Manager. And you can reference the HTML file using a path to include it in the Nix store.

{
  programs.firefox.preferences = {
    "browser.bookmarks.file" = ./bookmarks.html;
    "browser.places.importBookmarksHTML" = true;
  };
}

I haven’t tested that exact snippet but I use a similar trick to configure my bookmarks declaratively. Home Manager also does this, generating an HTML bookmark file for the bookmarks you give it in programs.firefox.profiles.<name>.bookmarks.

Edit: Changed incorrect mention of extraConfig Home Manager option to settings.

1 Like
{
  programs.firefox.preferences = {
    "browser.bookmarks.file" = ./bookmarks.html;
    "browser.places.importBookmarksHTML" = true;
  };
}

This code is managed by Home Manager?

That only shows up in Nix docs, not Home Manager.

It might still be possible to use those values in programs.firefox.profiles.<name>.extraConfig.

1 Like

Exactly, yeah. The above snippet is for NixOS. In Home Manager you would define that under the extraConfig option instead.

@t0ast I haven’t been able to get that to work. I’ve tried the bellow:

programs.firefox.profiles.<name>.extraConfig = ''
  browser.bookmarks.file = ./bookmarks.html;
  browser.places.importBookmarksHTML = true;
'';

I initally tried the same thing but w/o ; at the end of each config file line, neither have any affect.

<name> is a placeholder for whatever you want to name your Firefox profile. Also I just noticed I made a mistake: extraConfig is a multiline string that gets appended verbatim to the user.js file. programs.firefox.profiles.<name>.settings is what I meant. So an example config with Home Manager could be:

{
  programs.firefox.profiles.foobar.settings = {
    "browser.bookmarks.file" = ./bookmarks.html;
    "browser.places.importBookmarksHTML" = true;
  };
}

From the docs of programs.firefox.profiles.<name>.settings it looks like it’ll work.

I know what <name> represents.

@ReedClanton I tried your solution with your script and in my case, since I have a lot of bookmarks, it generates a big bookmarks.nix file that is ok. My only doubt is:

I would avoid to copy and paste a lot of rows in

programs.firefox.profiles.<name>.bookmarks = [

Is there a way to import inside this attribute the bookmarks.nix file?

Ya, builtins.readFile <pathToBookmarksNixFile>.

Also, as a heads up, I’ve noticed that if you set some other settings in Firefox, that programs.firefox.profiles.<name>.bookmarks value will stop working. Specifically some settings related to bookmarks set by programs.firefox.profiles.<name>.settings (as suggested earlier in this thread). I haven’t had time to trouble shoot it, so I could be wrong.

Edit: Come to think of it, that might not work. You may need to import it with import. I’ll test this out tomorrow and let you know. I’m about to get ready for bed now.

I lied. I did test it out, and it works. Just make sure that the contents of bookmarks.nix is formatted the same as it would be in the file, but without a ; at the end.

firefox.nix:

{
  programs.firefox.profiles.<name>.bookmarks = import <pathToBookmarksNixFile>;
}

bookmarks.nix:

[
  <outputOfMyScriptHere>
]

it works. Thank you. I have a last doubt: when I open Firefox, the bookmarks are imported inside “Bookmarks Menu” instead of “Bookmarks Toolbar”. Is there a setting to apply to move bookmarks directly in Bookmarks Toolbar instead of Bookmarks Menu?