Created
November 4, 2020 16:43
-
-
Save link0ff/699bf001fdf98d67cd516532515f9d51 to your computer and use it in GitHub Desktop.
Convert Trello JSON export files to Org-mode format
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 | |
# trello_json_to_org.rb | |
# convert JSON files exported from Trello to https://orgmode.org/ format | |
# | |
# Copyright (C) 2020 Juri Linkov <[email protected]> | |
# | |
# This program is free software; you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation; either version 2 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program; if not, write to the Free Software | |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
# Usage: ruby trello_json_to_org.rb trello_export.json > trello_export.org | |
# where trello_export.json is exported from a Trello board, | |
# and usually contains 8 hexadecimal characters in the file name. | |
# Post-processing: after converting to org-mode format, you might need to | |
# manually move TODO items that correspond to the finished state to the end | |
# of the "#+TODO:" line after the separator "|". | |
# It's useful first to export JSON to YAML with: | |
# ruby -rjson -ryaml -e 'puts(JSON.load(ARGF).to_yaml)' trello_export.json > trello_export.yaml | |
# to inspect the output, if you need to export more data to org-mode format. | |
require 'json' | |
def fix_label(label) | |
label.gsub(/\s+/, '_') | |
end | |
json = JSON.parse(ARGF.read, object_class: OpenStruct) | |
# Exit if it can't be org format file | |
exit unless json.prefs.canBeOrg | |
puts "#+TITLE: #{json.name}" | |
puts "#+AUTHOR: #{json.dig(:members, 0, :fullName)}" | |
puts "#+DATE: <#{json.dateLastActivity}>" | |
print "#+TODO: " | |
json.labelNames.each_pair do |_color, name| | |
print "#{fix_label(name)} " unless name.empty? | |
end | |
puts "|" # You can move some DONE labels after this "|" | |
puts | |
comments = Hash.new {|h,k| h[k]=[]} | |
json.actions.each do |action| | |
next unless action.type == 'commentCard' | |
comments[action.data.card.id] << action | |
end | |
json.lists.sort_by(&:pos).each do |list| | |
puts "* #{list.name}#{' :ARCHIVE:' if list.closed}" | |
puts | |
json.cards.sort_by(&:pos).each do |card| | |
next unless card.idList == list.id | |
print "** " | |
card.labels.each do |label| | |
print "#{fix_label(label.name)} " | |
end | |
puts "#{card.name}#{' :ARCHIVE:' if card.closed}" | |
puts " [#{card.dateLastActivity}]" | |
puts " DEADLINE: <#{card.due}>" if card.due | |
puts | |
card.idChecklists.each do |checklist_id| | |
json.checklists.sort_by(&:pos).each do |checklist| | |
next unless checklist.id == checklist_id | |
states = checklist.checkItems.group_by(&:state).transform_values(&:count) | |
puts "*** #{checklist.name} [#{states['complete'] || 0}/#{checklist.checkItems.size}]" | |
checklist.checkItems.sort_by(&:pos).each do |item| | |
puts " - [#{item.state == 'complete' ? 'X' : ' '}] #{item.name}" | |
end | |
end | |
puts | |
end | |
puts card.desc | |
puts | |
comments[card.id].each do |comment| | |
puts "*** Comment by #{comment.memberCreator.fullName}" | |
puts " [#{comment.date}]" | |
puts | |
puts comment.data.text | |
puts | |
end | |
end | |
end | |
colormap = { | |
green: '#61bd4f', # '#519839', | |
yellow: '#f2d600', # '#d9b51c', | |
orange: '#ff9f1a', # '#cd8313', | |
red: '#eb5a46', # '#b04632', | |
purple: '#c377e0', # '#89609e', | |
blue: '#0079bf', # '#055a8c', | |
sky: '#00c2e0', | |
lime: '#51e898', | |
pink: '#ff78cb', | |
black: '#344563', | |
} | |
puts | |
puts "* Local Variables :noexport:" | |
puts "\- Local Variables:" | |
print "- org-todo-keyword-faces: (" | |
json.labelNames.each_pair do |color, name| | |
print "\n- (\"#{fix_label(name)}\" . (:background \"#{colormap[color] || color}\" :foreground \"white\"))" unless name.empty? | |
end | |
puts ")" | |
puts "- End:" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment