class Doing::DayoneExport

Public Class Methods

render(wwid, items, variables: {}) click to toggle source
# File lib/doing/plugins/export/dayone_export.rb, line 46
def self.render(wwid, items, variables: {})

  return unless items.good?

  config = Doing.settings

  opt = variables[:options]
  trigger = opt[:output]
  digest = case trigger
           when /-days?$/
             :day
           when /-entries$/
             :entries
           else
             :digest
           end

  all_items = []
  days = {}
  flagged = false
  tags = []

  items.each do |i|
    day_flagged = false
    date_key = i.date.strftime('%Y-%m-%d')

    if String.method_defined? :force_encoding
      title = i.title.force_encoding('utf-8').link_urls(format: :markdown)
      note = i.note.map { |line| line.force_encoding('utf-8').strip.link_urls(format: :markdown) } if i.note
    else
      title = i.title.link_urls(format: :markdown)
      note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
    end

    title = "#{title} @section(#{i.section})" unless variables[:is_single]

    tags.concat(i.tag_array).sort!.uniq!
    flagged = day_flagged = true if i.tags?(config['marker_tag'])

    interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
    interval ||= false
    human_time = false
    if interval
      d, h, m = wwid.get_interval(i, formatted: false).format_time
      human_times = []
      human_times << format('%<d>d day%<p>s', d: d, p: d == 1 ? '' : 's') if d > 0
      human_times << format('%<h>d hour%<p>s', h: h, p: h == 1 ? '' : 's') if h > 0
      human_times << format('%<m>d minute%<p>s', m: m, p: m == 1 ? '' : 's') if m > 0
      human_time = human_times.join(', ')
    end

    done = i.tags?('done') ? ' ' : ' '

    item = {
      date_object: i.date,
      date: i.date.strftime('%a %-I:%M%p'),
      shortdate: i.date.relative_date,
      done: done,
      note: note,
      section: i.section,
      time: interval,
      human_time: human_time,
      title: title.strip,
      starred: day_flagged,
      tags: i.tag_array
    }
    all_items << item


    if days.key?(date_key)
      days[date_key][:starred] = true if day_flagged
      days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
      days[date_key][:entries].push(item)
    else
      days[date_key] ||= { tags: [], entries: [], starred: false }
      days[date_key][:starred] = true if day_flagged
      days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
      days[date_key][:entries].push(item)
    end
  end


  template = if config['export_templates']['dayone'] && File.exist?(File.expand_path(config['export_templates']['dayone']))
               IO.read(File.expand_path(config['export_templates']['dayone']))
             else
               self.template('dayone')
             end

  totals = opt[:totals] ? wwid.tag_times(format: :markdown, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''

  case digest
  when :day
    days.each do |k, hsh|
      title = "#{k}: #{variables[:page_title]}"
      to_dayone(template: template,
                title: title,
                items: hsh[:entries],
                totals: '',
                date: Time.parse(k),
                tags: tags,
                starred: hsh[:starred])
    end
  when :entries
    entry_template = if config['export_templates']['dayone_entry'] && File.exist?(File.expand_path(config['export_templates']['dayone_entry']))
                       IO.read(File.expand_path(config['export_templates']['dayone_entry']))
                     else
                       self.template('dayone-entry')
                     end
    all_items.each do |item|
      to_dayone(template: entry_template,
                title: '',
                items: [item],
                totals: '',
                date: item[:date_object],
                tags: item[:tags],
                starred: item[:starred])
    end
  else
    to_dayone(template: template,
                title: variables[:page_title],
                items: all_items,
                totals: totals,
                date: Time.now,
                tags: tags,
                starred: flagged)
  end

  @out = ''
end
settings() click to toggle source
# File lib/doing/plugins/export/dayone_export.rb, line 27
def self.settings
  {
    trigger: 'day(?:one)?(?:-(?:days?|entries))?',
    templates: [
      { name: 'dayone', trigger: 'day(?:one)?$', format: 'erb', filename: 'dayone.erb' },
      { name: 'dayone_entry', trigger: 'day(?:one)-entr(?:y|ies)?$', format: 'erb', filename: 'dayone-entry.erb' }
    ]
  }
end
template(trigger) click to toggle source
# File lib/doing/plugins/export/dayone_export.rb, line 37
def self.template(trigger)
  case trigger
  when /day(?:one)-entr(?:y|ies)?$/
    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone-entry.erb'))
  else
    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone.erb'))
  end
end
to_dayone(template: self.template(nil), title: 'doing', items: [], totals: '', date: Time.now, tags: [], starred: false) click to toggle source
# File lib/doing/plugins/export/dayone_export.rb, line 176
def self.to_dayone(template: self.template(nil), title: 'doing', items: [], totals: '', date: Time.now, tags: [], starred: false)
  mdx = DayOneRenderer.new(title, items, totals)

  engine = ERB.new(template)
  content = engine.result(mdx.get_binding)

  uuid = SecureRandom.uuid
  # uuid = `uuidgen`.strip

  plist = {
    'Creation Date' => date,
    'Creator' => { 'Software Agent' => 'Doing/2.0.0' },
    'Entry Text' => content,
    'Starred' => starred,
    'Tags' => tags.sort.uniq.delete_if { |t| t =~ /(done|cancell?ed|from)/ },
    'UUID' => uuid
  }

  container = File.expand_path('~/Library/Group Containers/')
  dayone_dir = Dir.glob('*.dayoneapp2', base: container).first
  import_dir = File.join(container, dayone_dir, 'Data', 'Auto Import', 'Default Journal.dayone', 'entries')
  FileUtils.mkdir_p(import_dir) unless File.exist?(import_dir)
  entry_file = File.join(import_dir, "#{uuid}.doentry")
  Doing.logger.debug('Day One Export:', "Exporting to #{entry_file}")
  File.open(entry_file, 'w') do |f|
    f.puts plist.to_plist
  end

  Doing.logger.count(:exported, level: :info, count: items.count, message: '%count %items exported to Day One import folder')
end