Exporting a DayOne commonplace book to org-roam

· 320 words · 2 minute read

I’ve kept some quotes in DayOne for years, and I frequently find myself coming back to them when I’m writing, either to actually use them or to just remember an idea. I thought it’d be handy to have them in my writing tool, so I used ChatGPT to help me write a quick exporter.

I’ll include that below, but the other thing to link to before your eyes glaze over with a hunk of Ruby is this useful post on using consult-ripgrep with org-roam for fulltext search from the org-roam Discourse. I’ve been careful to tag everything I’ve put in so far, but I won’t get to that with this batch of files, and I usually remember a keyword, anyhow. So they’re just tagged with “quotes” and “commonplace” for now.

The script just consumes the JSON that DayOne’s export function provides and coughs out formatted org-roam nodes. It uses DayOne’s uuid’s, but tacks on a few words – just in case? Maybe over time I’ll go clean up the titles but for now they’re just there to provide a hint when I search.

#!/usr/bin/env ruby

require 'json'
require 'date'

# Set these up before running
src_json = "/path/to/file.json"
destination_dir = "/path/to/export/dir"

# Read the JSON file
json_str = File.read(src_json)

# Parse the JSON string
data = JSON.parse(json_str)

def write_json_to_org_roam_files(json_str, path)
  data = JSON.parse(json_str)
  entries = data['entries']
  entries.each do |entry|
    created_date = DateTime.parse(entry['creationDate']).strftime('%Y%m%d%H%M%S')
    title = entry['text'].gsub(/^"/, '').gsub(/"$/, '').gsub(/[^a-zA-Z0-9 ]/, ' ').squeeze(' ').strip # replace non-alphanumeric with space, remove extra spaces
    first_words = title.split.first(5).join(' ').gsub(/[^a-zA-Z0-9]/, '-') # replace non-alphanumeric with dash
    uuid = first_words + '-' + entry['uuid']
    content = JSON.parse(entry['richText'])['contents'].map { |c| c['text'] }.join("\n")
    filename = "#{created_date}-#{first_words}.org".gsub(/^-/, '').gsub(/-$/, '').gsub(/-{2,}/,'-') # remove leading/trailing dashes and collapse multiple dashes
    file_content = <<~ORG_NODE.gsub(/^\s*/, '')
      :PROPERTIES:
      :ID: #{uuid}
      :END:
      #+title: #{first_words}
      #+filetags: :commonplace:quotes:

      #{content}
    ORG_NODE
    file = File.open(File.join(path, filename), 'w')
    file.write(file_content)
    file.close
  end
end
# Iterate over each entry
data['entries'].each do |entry|
  write_json_to_org_roam_files(json_str, File.expand_path(destination_dir))
end