Script: Export bookmarks structure as HTML file (for import in browser)

This script exports a HTML file ready for import in browser(s). It’s based on @cgrunenberg’s “Create Listing” script.

It accepts a selected group, smart group or feed. Every non-group child with a URL is included (exception: URLs starting with “mailto:”).

Bookmark folders are only created in the HTML file (and therefore in the browser) if a child group (or its child group and so on …) actually contain children with a URL, so it’s possible to select a group without worrying about ending up with empty browser bookmark folders.

If DEVONthink’s sort order is “unsorted” then what you see is what you’ll get in your browser.

There’s an option to use the selected record’s name as top bookmark folder, I find this useful to know where those bookmarks came from (especially in case of smart groups).

I’ll import my messy browser bookmarks in DEVONthink, organize them (e.g. deduplicate), replicate where it makes sense, export, and hopefully end up with a nice and useful collection.

-- Export bookmarks structure as HTML file (for import in browser)
-- Based on Christian Grunenberg's "Create Listing" script

property useEnclosingFolder : true

property theHTML_Start : "<!DOCTYPE NETSCAPE-Bookmark-file-1>" & linefeed & tab & "<HTML>" & linefeed & tab & "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">" & linefeed & tab & "<Title>Lesezeichen</Title>" & linefeed & tab & "<H1>Lesezeichen</H1>"
property theHTML_End : linefeed & "</HTML>"

tell application id "DNtp"
	try
		set theRecords to selection of viewer window 1
		if theRecords = {} or (count theRecords) > 1 then error "Select one group, smart group or feed."
		if (type of item 1 of theRecords) as string is not in {"«constant ****DTgr»", "«constant ****DTsg»", "group", "smart group", "feed"} then error "Select one group, smart group or feed."
		
		show progress indicator "Creating Bookmark Listing..." with cancel button
		if useEnclosingFolder = true then
			set theHTML_Start to theHTML_Start & linefeed & (ASCII character 9) & "<DT><H3 FOLDED>" & (name of item 1 of theRecords) & "</H3>" & linefeed & (ASCII character 9) & "<DL><p>"
			set theHTML_End to linefeed & (ASCII character 9) & "</DL><p>" & theHTML_End
		end if
		set theTabs to (ASCII character 9)
		set theHTMLSource to theHTML_Start & my createBookmarkListing(item 1 of theRecords, theTabs) & theHTML_End
		set theName to ("Bookmarks Export \"" & (name of item 1 of theRecords) as string) & "\""
		set theHTMLrecord to create record with {type:html, name:theName, source:theHTMLSource} in incoming group
		export record theHTMLrecord to (POSIX path of (path to desktop)) as string
		delete record theHTMLrecord
		
		hide progress indicator
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on createBookmarkListing(theGroup, theTabs)
	tell application id "DNtp"
		try
			set thisListing to ""
			set thisCount to 0
			set theseRecords to children of theGroup
			set theseRecordCount to (count theseRecords)
			
			repeat with thisRecord in theseRecords
				set thisCount to thisCount + 1
				set thisName to name of thisRecord
				set thisURL to URL of thisRecord
				set thisType to (type of thisRecord) as string
				if thisType is in {"«constant ****DTgr»", "«constant ****DTsg»", "group", "smart group", "feed"} then
					set containsURLs to true
					if thisType = "«constant ****DTgr»" or thisType = "group" then set containsURLs to my contains_URLs(thisRecord)
					if containsURLs = true then
						step progress indicator thisName
						set thisListing to thisListing & linefeed & theTabs & "<DT><H3 FOLDED>" & thisName & "</H3>" & linefeed & theTabs & "<DL><p>"
					end if
					set thisGroupsListing to my createBookmarkListing(thisRecord, theTabs & (ASCII character 9))
					set thisListing to thisListing & thisGroupsListing & linefeed & theTabs & "</DL><p>"
				else
					if thisURL ≠ "" and thisURL does not start with "mailto:" then
						set revPath to reverse of characters of (filename of thisRecord as string) as string
						set thisSuffix to reverse of characters 1 thru ((offset of "." in revPath) - 1) in revPath as string
						if thisName ends with thisSuffix then set thisName to characters 1 thru -((length of thisSuffix) + 2) in thisName as string
						set thisListing to thisListing & linefeed & theTabs & "<DT><A HREF=\"" & thisURL & "\">" & thisName & "</A>"
					end if
				end if
			end repeat
			
			return thisListing
		on error error_message number error_number
			error -128
		end try
	end tell
end createBookmarkListing

on contains_URLs(theGroup)
	tell application id "DNtp"
		try
			set theChildren to (children of theGroup whose type is not group) & (children of theGroup whose type is group)
			repeat with thisChild in theChildren
				if type of thisChild = group then
					my contains_URLs(thisChild)
				else
					set thisURL to URL of thisChild
					if thisURL ≠ "" and thisURL does not start with "mailto:" then return true
				end if
			end repeat
			return false
		on error error_message number error_number
			error -128
		end try
	end tell
end contains_URLs
1 Like
  • The HMTL file is exported to your desktop

  • To import in Safari:

    • Menu File > Import From > Bookmarks HTML file

    • Choose the exported HTML file

    • Menu Bookmarks > Edit Bookmarks

    • If you want to replace your existing bookmarks delete them now (but make sure to not delete the imported folder)

    • Open the imported folder

    • Drag everything from subfolder “Bookmarks Bar” (I guess that’s the name …) to the “Favorites” folder

    • Drag everything from inside the imported folder where you want it to go

  • This should work with every browser that supports importing bookmarks as HTML file.