Skip to content

Instantly share code, notes, and snippets.

@angelamancini
Created May 20, 2017 16:14
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save angelamancini/c42996c0db9d50c9d73e61422daca801 to your computer and use it in GitHub Desktop.
Save angelamancini/c42996c0db9d50c9d73e61422daca801 to your computer and use it in GitHub Desktop.
Converts Quiver notebook exports to Evernote *.enex files. Only tested with text and code cells. This *was not tested* with any other cell types.
# Before running this script, go to Quiver and export all notebooks into json/quiver format
# Place them in a folder called `exports` in the same directory as this script.
# In terminal, run `ruby quiver-to-evernote.rb`
# Check for presence of required gems.
# If not present, install the gems
["rubygems", "sanitize"].each do |gem|
begin
gem "#{gem}"
rescue Gem::LoadError
`gem install #{gem}`
Gem.clear_paths
end
end
require 'date'
require 'json'
require 'rubygems'
require 'sanitize'
# Read the exports folder
Dir.chdir('exports')
# find all the notebooks as .qvbotebook files
notebooks = Dir.glob('*').select {|f| File.directory? f}
# Loop through the notebooks and find all the notes
notebooks.each do |notebook|
name = notebook.gsub(/.qvnotebook$/,'')
file_name = "../imports/#{name}.enex"
puts "Reading Notebook: #{name}"
file_date = File.mtime(notebook).to_time.utc.strftime("%Y%m%dT%H%M%SZ")
# create the imports/notebook.enex file
file = File.open(file_name, 'w')
# write the file header
file_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE en-export SYSTEM \"http://xml.evernote.com/pub/evernote-export3.dtd\">
<en-export export-date=\"#{file_date}\" application=\"Evernote\" version=\"Evernote Mac 6.11 (454874)\">\n\n\n"
file << file_header
notes = Dir.glob("#{notebook}/*").select {|f| File.directory? f}
puts "#{notes.count} notes"
# loop through each note folder and read the content.json and meta.json
notes.each do |note|
puts "Reading Note: #{note}"
content = JSON.parse(File.read("#{note}/content.json"))
meta = JSON.parse(File.read("#{note}/meta.json"))
text = ""
content['cells'].each do |cell|
# If the cells are code, wrap in temporary code blocks, they will be replaced later
if cell['type'] == 'code'
text += "<code>#{cell['data'].gsub("\n","<br/>")}</code>"
else
text += cell['data']
end
end
# Sanatize the text of most html tags. I found that some styles really make evernote go nuts
sanitized_text = Sanitize.clean(text, Sanitize::Config::BASIC).strip
# I really hate this, the code blocks in evernote are not just <code> tags, they are this awful and ugly thing that would've gotten stripped out of our sanatized text.
code_bock_begining = '<div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;-en-codeblock:true;"><div>'
code_block_end = '<br/></div></div><div><br/></div>'
# Replace the problem characeters. This list can be changed except for the code tags.
replace = { '&' => '&amp;', '<br>' => '<br />', '<br /><br />' => '<br />', '<code>' => code_bock_begining, '</code>' => code_block_end }
re = Regexp.new(replace.keys.map { |x| Regexp.escape(x) }.join('|'))
clean_text = sanitized_text.gsub(re, replace)
tags = ""
# Write the tags
meta['tags'].map { |t| tags += "<tag>#{t}</tag>"}
# write the note into the file, making sure no ampersands are in the title, that messed my import up
file << "<note><title>#{content['title'].gsub('&','&amp;')}</title><content><![CDATA[ <en-note>#{clean_text}</en-note>]]></content><created>#{Time.at(meta['created_at']).to_time.utc.strftime('%Y%m%dT%H%M%SZ')}</created><updated>#{Time.at(meta['updated_at']).to_time.utc.strftime('%Y%m%dT%H%M%SZ')}</updated>#{tags}<note-attributes></note-attributes></note>\n\n\n"
end
# write the end tag on the file and close
file << "\n</en-export>"
file.close
end
# You should have a directory called `imports` and one *.enex file for every quiver notebook.
# In evernote, go to File > Import and import in the file.
@RichardJTorres
Copy link

I just used this to move from quiver to evernote, mostly because I want a note taking app with Linux desktop options, really appreciate this. However, I had two issues that I had to fix before the script would work (I'm on OSX):

  1. gem "rubygems" would not install. It's not used anywhere in the script, so I simply removed it.
  2. File.open() does not seem to create missing directories, so I had to manually create the exports folder.

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment