Package: bkmk
bkmkbkmkis a Python library and command-line utility to convert between
different bookmarks formats. It has been tested thoroughly on the following
formats, and supports conversion between any of them:XBEL - a standardised and precisely-defined XML-based formatNetscape HTML - an imprecisely-defined ad-hoc external interchange format
supported by most browsers including Firefox and Chrome, as well as being
used internally by Firefox and Mozilla-based browsersChrome JSON - an undocumented format, used internally by ChromebkmkJSON - our own format, which expresses a superset of all the features
of all the above formats. The format is extremely simple and will remain
stable across many versions of this tool, and files written in it can easily
be manipulated using common ecosystem tools such asjq(1). For a detailed
specification, seebelow.Install via pip:$ pip3 install -U bkmkAll the functionality of the CLI is mirrored in the API; seebkmk --helporpydoc3 bkmkfor details.CLI examplesConvert to Netscape HTML format, which can be imported into most browsers:$ bkmk <input-file> backup.htmlDirectly override Chrome's internal bookmarks JSON. (Do this only when Chrome is closed.)$ bkmk --fill-special --cull-special -t chrome-json <input-file> ~/.config/chrome/Default/BookmarksRetrieve a remote XBEL backup, convert it intobkmkJSON, make sure all elements have IDs, then process it further withjq.$ curl https://backupserver/bk.xbel | bkmk --fill-ids -f xbel -t bkmk-json | jq <some-complex-script> > <output-file>API examplesfrombkmkimportBookmarks,FORMAT_EXTSinput_filenames="a.xbel b.xbel".split()output_filestem="combined"output_exts=".json .html".split()# combine several bookmark files into onebk=Bookmarks.new()forfnininput_filenames:withopen(fn)asfp:bm=Bookmarks.read(fp,"xbel")bm.root.name=fnbm.prefix_ids(fn.replace(".xbel","-"))bk.root.children.append(bm.root)# fill in special top-level folders that browsers sometimes expect/require when importingbk.fill_special()# fill in timestamps for completenessbk.fill_timestamps()# output in several different formatsforoinoutput_exts:withopen("%s%s"%(output_filestem,o),"w")asfp:bk.write(fp,FORMAT_EXTS[o][0],cull_special=True)bkmk JSON format specThe JSON format mirrors our AST type, which is exposed in the public API in the
top-levelbkmkmodule, re-exported frombkmk.base.Meta-documentation. In the below specification,unix_microsrefers to a JSON integer that represents microseconds since the
Unix epoch, ignoring leap seconds, and can be negative.stringrefers to anon-emptyJSON string. Attributes that are empty JSON
strings are effectively omitted.Required attributes are inbold, all other attributes are optional.Specification.Every object supports the following attributes:type: string, possible valuesseparator,bookmark,folder,
indicates which further attributes the object may have as defined below.id: string, must be unique under the root object, for use as a unique
reference by reading tools.date_added: unix_micros, when this object was added into the AST.bookmark,folderadditionally support the following attributes:name: string, title or short description of this folder or bookmark.icon: string,Data URLof the icon for this folder or bookmark.date_modified: unix_micros, when this object's attributes were last
modified, excluding remote-mirroring attributes such asurl_date_modified.bookmarkadditionally supports the following attributes:url: string, URL target of this bookmark.url_date_modified: unix_micros, when the URL target was last modified on the remote side.url_date_visited: unix_micros, when the URL target was last visited (retrieved) by the local side.folderadditionally supports the following attributes:children: list[object], contents of this folder.special: string, possible valuesTOOLBAR,OTHER_UNFILED,SAVED_TABS,
indicates a special status of the folder. On conversion, this is mapped to
the corresponding special values of the target format, and treated specially
by the target browser.For interoperability with other formats, we recommend that:the root object should have"type": "folder"and nospecialattribute.folders withspecialattributes should not be placed inside each other.
For maximum interoperability they should be immediate children of the root
folder - some formats require this, others don't.