Last active
March 30, 2020 18:47
-
-
Save mmower/e1af40cb84b9189fadf402ee4dc5c690 to your computer and use it in GitHub Desktop.
Ruby script that converts a JSON export of Pinboard.in bookmarks into a properly tagged Markdown file to import into Roam
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -w | |
# frozen_string_literal: true | |
# | |
# usage | |
# chmod +x pinboard_converter.rb | |
# ./pinboard_converter.rb -t [pinboard_export_file] > tag_map.yml | |
# edit tag_map.yml | |
# ./pinboard_converter.rb [pinboard_export_file] tag_map.yml > [roam_import_file] | |
# import [roam_import_file] into Roam | |
# | |
# optionally pass -d and a file with a list of URL filters (one per line) for | |
# links that should not pass through into the markdown file | |
# | |
require 'optparse' | |
require 'json' | |
require 'yaml' | |
options = {} | |
optparse = OptionParser.new do |opts| | |
opts.banner = 'Usage: pinboard_converter [options] pinboard_export_file tag_map_file' | |
options[:tag_map] = false | |
opts.on('-t', '--tags', 'Output a tag map file') do | |
options[:tag_map] = true | |
end | |
opts.on('-d', '--domain-filter FILTER', 'Filter link domains using FILTER') do |filter_file| | |
options[:domain_filter] = filter_file | |
end | |
end | |
optparse.parse! | |
filters = if options[:domain_filter] | |
File.readlines(options[:domain_filter]).map { |filter| Regexp.new(filter.strip) } | |
else | |
[] | |
end | |
def filter_link(filters, href) | |
filters.find { |filter| filter =~ href } | |
end | |
def non_empty_str(s) | |
s == '' ? nil : s | |
end | |
def convert_tags(tag_map, tags) | |
tags.strip.split(/\s+/).map { |tag| non_empty_str(tag_map[tag]) }.compact.uniq.map do |tag| | |
if tag =~ /\s+/ | |
"#[[#{tag}]]" | |
else | |
"##{tag}" | |
end | |
end | |
end | |
pins = JSON.parse(File.read(ARGV[0])) | |
if options[:tag_map] | |
tags = pins.each_with_object({}) do |pin, tag_acc| | |
pin['tags'].split(/\s+/).map { |tag| tag }.each do |tag| | |
tag_acc[tag] = tag | |
end | |
end.sort.to_h | |
puts YAML.dump(tags) | |
else | |
tag_map = YAML.safe_load(File.read(ARGV[1])) | |
items = pins.map do |pin| | |
href = pin['href'].strip | |
if filter_link(filters, href) | |
nil | |
else | |
desc = pin['description'].strip | |
link = "- [#{desc}](#{href})" | |
tags = convert_tags( tag_map, pin['tags'] ) | |
if tags.empty? | |
link | |
else | |
"#{link} #{tags.join(' ')}" | |
end | |
end | |
end | |
puts items.compact.join("\n") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment