Skip to content

Instantly share code, notes, and snippets.

@EvanHahn
Created April 29, 2023 23:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EvanHahn/cd5c705063b0300ffe6e8346f4e104a0 to your computer and use it in GitHub Desktop.
Save EvanHahn/cd5c705063b0300ffe6e8346f4e104a0 to your computer and use it in GitHub Desktop.
function stringify({ keys, objects }) {
let result = "";
result += row(keys);
for (const obj of objects) {
result += "\r\n";
result += row(values(obj, keys));
}
return result;
}
function row(values) {
return values.map(serialize).join(",");
}
function serialize(value) {
switch (typeof value) {
case "string":
return serializeString(value);
case "number":
return Number.isNaN(value) ? "" : String(value);
case "bigint":
case "boolean":
return String(value);
case "undefined":
return "";
case "object":
if (value === null) return "";
return serializeDate(value);
default:
throw new MissingCaseError(value);
}
}
function serializeString(str) {
return shouldFieldBeQuoted(str) ? `"${str.replace(/"/gm, '""')}"` : str;
}
function shouldFieldBeQuoted(str) {
return str.includes(",") || str.includes('"') || str.includes("\r\n");
}
function serializeDate(date) {
return isNaN(date.valueOf()) ? "" : date.toISOString();
}
function values(obj, keys) {
return keys.map((key) => obj[key]);
}
class MissingCaseError extends Error {
constructor(_value) {
super("This should be impossible");
}
}
function formatTask(task) {
return {
"Completed Date": task.getCompletedDate(),
Completed: task.isCompleted(),
"Created Date": task.getCreatedDate(),
"Due Date": formatDateThatMightHaveTime(
task.getDueDate(),
task.hasDueTime()
),
"Estimate (minutes)": task.getEstimate()?.getMinutes() || null,
ID: task.getId(),
List: task.getList().getName(),
"Modified Date": task.getModifiedDate(),
Name: task.getName(),
"Parent Task ID": task.getParent()?.getId() || null,
Permalink: task.getPermalink(),
Priority: formatPriority(task.getPriority()),
Recurring: task.isRecurring(),
"Start Date": formatDateThatMightHaveTime(
task.getStartDate(),
task.hasStartTime()
),
URL: task.getUrl()?.toString() || null,
};
}
function formatDateThatMightHaveTime(date, hasTime) {
if (!date || isNaN(date.valueOf())) return null;
return hasTime ? date : date.toISOString().slice(0, 10);
}
function formatPriority(priority) {
if (!priority) return null;
const result = priority.toString();
return result === "NoPriority" ? null : result;
}
function main() {
const tasks = rtm.getSelectedTasks();
if (!tasks.length) {
return rtm.newMessage(
"No tasks selected",
"Select 1 or more tasks to export as CSV."
);
}
const csvData = stringify({
keys: ["Name", "Completed", "Estimate (minutes)", "Due Date", "Priority"],
objects: tasks.map(formatTask),
});
return rtm.newFile(csvData, rtm.MediaType.CSV, "remember_the_milk.csv");
}
main();
@prasi00
Copy link

prasi00 commented Sep 25, 2023

Thanks thanks thanks!

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