initial commit
This commit is contained in:
commit
4646cecd92
|
@ -0,0 +1,3 @@
|
||||||
|
md2imap/mbox
|
||||||
|
md2imap/*.imap
|
||||||
|
md2imap/input/*
|
|
@ -0,0 +1,8 @@
|
||||||
|
# cryptee-to-markdown
|
||||||
|
A simple js script to convert your .uecd [Cryptee](https://github.com/cryptee) documents to markdown.
|
||||||
|
|
||||||
|
**Deprecated**: see delta2md instead
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
* Download .uecd files from the crypt.ee app.
|
||||||
|
* call `node node-ui.js <inputUecdFolder>` or open `web-ui.html` in browser.
|
|
@ -0,0 +1,117 @@
|
||||||
|
function getMarkDown(jsonInput)
|
||||||
|
{
|
||||||
|
function startLastWith(text)
|
||||||
|
{
|
||||||
|
temp = result.split('\n');
|
||||||
|
temp[temp.length - 1] = text + temp[temp.length - 1];
|
||||||
|
result = temp.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function dressUp(text, cloth)
|
||||||
|
{
|
||||||
|
return cloth + text + cloth;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCodeBlocks()
|
||||||
|
{
|
||||||
|
temp = result.split('\n');
|
||||||
|
var code = false;
|
||||||
|
for (var i in temp)
|
||||||
|
{
|
||||||
|
if (temp[i].startsWith("~~~"))
|
||||||
|
{
|
||||||
|
if (!code)
|
||||||
|
{
|
||||||
|
code = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp[i] = temp[i].substr(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (code)
|
||||||
|
{
|
||||||
|
temp[i] += "~~~";
|
||||||
|
code = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = temp.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = JSON.parse(jsonInput);
|
||||||
|
var result = "";
|
||||||
|
var code = false;
|
||||||
|
|
||||||
|
for (var i in data.ops)
|
||||||
|
{
|
||||||
|
var elt = data.ops[i];
|
||||||
|
var text = elt.insert;
|
||||||
|
|
||||||
|
if (text.image)
|
||||||
|
{
|
||||||
|
var alt = "";
|
||||||
|
if (elt.attributes && elt.attributes.alt) alt = elt.attributes.alt;
|
||||||
|
text = "![" + alt + "](" + text.image + ")";
|
||||||
|
}
|
||||||
|
if (text.divider)
|
||||||
|
{
|
||||||
|
text = '____\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elt.attributes)
|
||||||
|
{
|
||||||
|
var attr = elt.attributes;
|
||||||
|
if (attr.tag)
|
||||||
|
{
|
||||||
|
text = "#" + text;
|
||||||
|
}
|
||||||
|
if (attr.header)
|
||||||
|
{
|
||||||
|
startLastWith("#".repeat(attr.header) + " " );
|
||||||
|
}
|
||||||
|
if (attr.list == "bullet")
|
||||||
|
{
|
||||||
|
startLastWith("* ");
|
||||||
|
}
|
||||||
|
if (attr.list == "ordered")
|
||||||
|
{
|
||||||
|
startLastWith("1. ");
|
||||||
|
}
|
||||||
|
if (attr.list == "unchecked")
|
||||||
|
{
|
||||||
|
startLastWith("- [ ] ");
|
||||||
|
}
|
||||||
|
if (attr.list == "checked")
|
||||||
|
{
|
||||||
|
startLastWith("- [x] ");
|
||||||
|
}
|
||||||
|
if (attr.italic)
|
||||||
|
{
|
||||||
|
text = dressUp(text, "*");
|
||||||
|
}
|
||||||
|
if (attr.bold)
|
||||||
|
{
|
||||||
|
text = dressUp(text, "**");
|
||||||
|
}
|
||||||
|
if (attr["code-block"])
|
||||||
|
{
|
||||||
|
startLastWith("~~~");
|
||||||
|
}
|
||||||
|
if (attr.blockquote)
|
||||||
|
{
|
||||||
|
startLastWith("> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// post processing
|
||||||
|
createCodeBlocks();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module !== "undefined")
|
||||||
|
{
|
||||||
|
module.exports.convert = getMarkDown;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
let getMarkDown = require("./cryptee-to-markdown.js");
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
const folder = process.argv[2];
|
||||||
|
const files = fs.readdirSync(folder);
|
||||||
|
|
||||||
|
for (var i in files)
|
||||||
|
{
|
||||||
|
const file = files[i];
|
||||||
|
|
||||||
|
if (file.indexOf('uecd') === -1) continue;
|
||||||
|
console.log(file);
|
||||||
|
|
||||||
|
var data = fs.readFileSync( path.join(folder, file));
|
||||||
|
|
||||||
|
var md = getMarkDown.convert(data);
|
||||||
|
|
||||||
|
fs.writeFile(path.join(folder, file.replace(".uecd", ".md")), md, function (err)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="./cryptee-to-markdown.js"></script>
|
||||||
|
<script>
|
||||||
|
function convert()
|
||||||
|
{
|
||||||
|
var json = document.getElementById("input").value;
|
||||||
|
var md =getMarkDown(json);
|
||||||
|
console.log(md);
|
||||||
|
document.getElementById("result").innerHTML = "<pre>" + md + "</pre>";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<textarea id="input"></textarea>
|
||||||
|
<button onclick="convert();">Convertir</button>
|
||||||
|
<div id="result"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,231 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
var inputFolder = "notes";
|
||||||
|
var outputFolder = "result";
|
||||||
|
var includeheaders = true;
|
||||||
|
|
||||||
|
var files = fs.readdirSync(inputFolder);
|
||||||
|
|
||||||
|
for (var i in files)
|
||||||
|
{
|
||||||
|
var file = files[i];
|
||||||
|
if (file.indexOf(".uecd") === -1)
|
||||||
|
{
|
||||||
|
fs.copyFileSync(path.join(inputFolder, file), path.join(outputFolder, file));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var data = fs.readFileSync(path.join(inputFolder, file), 'utf8');
|
||||||
|
var md = mdify(JSON.parse(data), file);
|
||||||
|
fs.writeFileSync(path.join(outputFolder, file).replace(".uecd", ".md"), md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mdify(data, file)
|
||||||
|
{
|
||||||
|
var result = "";
|
||||||
|
var tags = [];
|
||||||
|
|
||||||
|
for (var i in data.ops)
|
||||||
|
{
|
||||||
|
var op = data.ops[i];
|
||||||
|
|
||||||
|
if (op.insert.image)
|
||||||
|
{
|
||||||
|
// inline base64
|
||||||
|
//result += "![](" + op.insert.image + ")";
|
||||||
|
|
||||||
|
//external
|
||||||
|
var alt = op.attributes && op.attributes.alt ? op.attributes.alt : "";
|
||||||
|
if (op.insert.image.indexOf("data:image") !== -1)
|
||||||
|
{
|
||||||
|
var buffer = Buffer.from(op.insert.image.replace(/^data:image\/jpeg;base64,/, ""), "base64");
|
||||||
|
var imageFileName = file.replace(".uecd", i + ".jpeg");
|
||||||
|
fs.writeFileSync(path.join(outputFolder, imageFileName), buffer);
|
||||||
|
result += "![" + alt + "](" + imageFileName + ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += "![" + alt + "](" + op.insert.image + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!op.attributes)
|
||||||
|
{
|
||||||
|
if (op.insert.divider)
|
||||||
|
{
|
||||||
|
result += "---\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op.attributes.italic)
|
||||||
|
{
|
||||||
|
result += "*" + op.insert + "*";
|
||||||
|
}
|
||||||
|
else if (op.attributes.bold)
|
||||||
|
{
|
||||||
|
result += "**" + op.insert + "**";
|
||||||
|
}
|
||||||
|
else if (op.attributes.underline)
|
||||||
|
{
|
||||||
|
result += "__" + op.insert + "__";
|
||||||
|
}
|
||||||
|
else if (op.attributes.strike)
|
||||||
|
{
|
||||||
|
result += "~~" + op.insert + "~~";
|
||||||
|
}
|
||||||
|
else if (op.attributes.tag)
|
||||||
|
{
|
||||||
|
//result += "#" + op.insert;
|
||||||
|
tags.push(op.insert);
|
||||||
|
}
|
||||||
|
else if (op.attributes.header)
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "#".repeat(op.attributes.header) + " " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else if (op.attributes.link)
|
||||||
|
{
|
||||||
|
if (op.insert == op.attributes.link)
|
||||||
|
{
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += "[" + op.insert + "](" + op.attributes.link + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op.attributes.code)
|
||||||
|
{
|
||||||
|
result += "`" + op.insert + "`";
|
||||||
|
}
|
||||||
|
else if (op.attributes.list == "bullet")
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "\t".repeat(op.attributes.indent) + "* " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else if (op.attributes.list == "unchecked")
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "\t".repeat(op.attributes.indent) + "[ ] " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else if (op.attributes.list == "checked")
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "\t".repeat(op.attributes.indent) + "[x] " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else if (op.attributes.list == "ordered")
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "\t".repeat(op.attributes.indent) + "1. " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
else if (op.attributes.file)
|
||||||
|
{
|
||||||
|
result += "[[" + op.attributes.file.filetitle + "]]";
|
||||||
|
|
||||||
|
// traditional link
|
||||||
|
//result += "[" + op.attributes.file.filetitle + "](" + op.attributes.file.filetitle + ".md)";
|
||||||
|
}
|
||||||
|
else if (op.attributes["code-block"])
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "```" + result[result.length - 1] + "```";
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert.replace(/\n\n/g, "\n``````\n");;
|
||||||
|
}
|
||||||
|
else if (op.attributes.blockquote)
|
||||||
|
{
|
||||||
|
var result = result.split("\n");
|
||||||
|
result[result.length - 1] = "> " + result[result.length - 1];
|
||||||
|
result = result.join("\n");
|
||||||
|
result += op.insert.replace(/\n\n/g, "\n> \n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += op.insert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post processing
|
||||||
|
|
||||||
|
// remove nbsp, indent and trailing
|
||||||
|
result = result.replace(/ /g, " ");
|
||||||
|
result = result.replace(/\n[ ]*/g, "\n");
|
||||||
|
result = result.replace(/[ ]*\n/g, "\n");
|
||||||
|
|
||||||
|
// insert line endings
|
||||||
|
result = result.split('\n');
|
||||||
|
var blockMarkers = ["* ", "1. ", "> ", "```", "["];
|
||||||
|
for (var i = 0; i < result.length; i++)
|
||||||
|
{
|
||||||
|
var inBlock = false;
|
||||||
|
for (var j in blockMarkers)
|
||||||
|
{
|
||||||
|
var block = blockMarkers[j];
|
||||||
|
if (result[i].replace(/\t/g, "").startsWith(block) && result[i + 1].replace(/\t/g, "").startsWith(block))
|
||||||
|
{
|
||||||
|
inBlock = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inBlock && Boolean(result[i + 1]))
|
||||||
|
{
|
||||||
|
result.splice(i + 1, 0, "");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result.join("\n");
|
||||||
|
|
||||||
|
// merge code blocks
|
||||||
|
result = result.replace(/```\n```/g, "\n");
|
||||||
|
result = result.replace(/```/g, "\n```\n");
|
||||||
|
|
||||||
|
// escape ~ in unix path
|
||||||
|
result = result.replace(/~\//g, "\\~/");
|
||||||
|
|
||||||
|
// headers
|
||||||
|
if (includeheaders)
|
||||||
|
{
|
||||||
|
var headers =
|
||||||
|
{
|
||||||
|
title: file.replace(".uecd", ""),
|
||||||
|
tags: tags.join(", ")
|
||||||
|
};
|
||||||
|
|
||||||
|
if (/[.|mars|mai|juin|août] 202\d /.test(file))
|
||||||
|
{
|
||||||
|
var index = file.indexOf("202");
|
||||||
|
headers.title = headers.title.substring(index + 5);
|
||||||
|
headers.date = file.substring(0, index + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
var headersmd = "---\n";
|
||||||
|
for (var i in headers)
|
||||||
|
{
|
||||||
|
headersmd += i + ": " + headers[i] + "\n";
|
||||||
|
}
|
||||||
|
headersmd += "---";
|
||||||
|
|
||||||
|
if (result[0] != "\n") headersmd += "\n";
|
||||||
|
if (result[1] != "\n") headersmd += "\n";
|
||||||
|
|
||||||
|
result = headersmd + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
# export-turtl-notes
|
||||||
|
A simple python script to export your [turtl](https://github.com/turtl) notes.
|
||||||
|
|
||||||
|
What the script does:
|
||||||
|
* Export your notes as markdown files.
|
||||||
|
* Photos and files are also exported (without the associated text).
|
||||||
|
* A new folder is created for each board, containg the files.
|
||||||
|
* Tags are lost.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
* Export your turtl profile from the turtl app
|
||||||
|
* launch `python export-turtl-notes.py` next to turtl-backup.json
|
|
@ -0,0 +1,62 @@
|
||||||
|
import base64
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
def findboard(id):
|
||||||
|
for board in data['boards']:
|
||||||
|
if id == board['id']:
|
||||||
|
return board['title']
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def clean(text):
|
||||||
|
return "".join(c if c.isalnum() else " " for c in text)
|
||||||
|
|
||||||
|
|
||||||
|
f = open('turtl-backup.json', encoding='utf-8')
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
if not os.path.isdir('turtl'):
|
||||||
|
os.mkdir('turtl')
|
||||||
|
|
||||||
|
for folder in data['boards']:
|
||||||
|
path = os.path.join('turtl', folder['title'])
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
os.mkdir(path)
|
||||||
|
|
||||||
|
untitledcounter = 1
|
||||||
|
|
||||||
|
for note in data['notes']:
|
||||||
|
|
||||||
|
type = note['type']
|
||||||
|
title = note['title']
|
||||||
|
if title == '':
|
||||||
|
title = 'untitled' + str(untitledcounter)
|
||||||
|
untitledcounter += 1
|
||||||
|
|
||||||
|
print(title)
|
||||||
|
|
||||||
|
if type == 'text':
|
||||||
|
filename = clean(title) + '.md'
|
||||||
|
with open(os.path.join('turtl', findboard(note['board_id']), filename), 'wb') as n:
|
||||||
|
n.write(note['text'].encode('utf-8'))
|
||||||
|
n.close()
|
||||||
|
|
||||||
|
if type == 'image' or type == 'file':
|
||||||
|
file = note['file']
|
||||||
|
filename = file['name']
|
||||||
|
for fileref in data['files']:
|
||||||
|
if fileref['id'] == note['id']:
|
||||||
|
b64 = fileref['data']
|
||||||
|
with open(os.path.join('turtl', findboard(note['board_id']), filename), 'wb') as n:
|
||||||
|
n.write(base64.decodebytes(b64.encode('utf-8')))
|
||||||
|
n.close()
|
||||||
|
|
||||||
|
if type == 'link':
|
||||||
|
url = note['url']
|
||||||
|
text = url + '\r\n' + note['text']
|
||||||
|
filename = clean(title) + '.md'
|
||||||
|
with open(os.path.join('turtl', findboard(note['board_id']), filename), 'wb') as n:
|
||||||
|
n.write(text.encode('utf-8'))
|
||||||
|
n.close()
|
||||||
|
|
||||||
|
f.close()
|
|
@ -0,0 +1,2 @@
|
||||||
|
# export-wm3
|
||||||
|
A js script to export your [writemonkey3](https://writemonkey.com/wm3/) documents as flat markdown files.
|
|
@ -0,0 +1,26 @@
|
||||||
|
var fs = require('fs')
|
||||||
|
|
||||||
|
var filePath = process.argv[2];
|
||||||
|
|
||||||
|
var fileContent = fs.readFileSync(filePath, 'utf8');
|
||||||
|
var data = fileContent.split("\n");
|
||||||
|
var documents = {};
|
||||||
|
for (var i in data)
|
||||||
|
{
|
||||||
|
if (!data[i]) continue;
|
||||||
|
|
||||||
|
var file = JSON.parse(data[i]);
|
||||||
|
if (file.nam && file.txt && !file.del)
|
||||||
|
{
|
||||||
|
if (!documents[file.nam] || documents[file.nam].dtm < file.dtm)
|
||||||
|
{
|
||||||
|
documents[file.nam] = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in documents)
|
||||||
|
{
|
||||||
|
console.log(documents[i].nam);
|
||||||
|
fs.writeFileSync(documents[i].nam + '.md', documents[i].txt, 'utf8');
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
from markdownify import markdownify
|
||||||
|
import imaplib
|
||||||
|
import email
|
||||||
|
from email.header import decode_header
|
||||||
|
import os
|
||||||
|
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
imapserver = ""
|
||||||
|
|
||||||
|
if not os.path.isdir('notes'):
|
||||||
|
os.mkdir('notes')
|
||||||
|
|
||||||
|
def clean(text):
|
||||||
|
return "".join(c if c.isalnum() else "_" for c in text)
|
||||||
|
|
||||||
|
# number of top emails to fetch
|
||||||
|
N = 200
|
||||||
|
|
||||||
|
imap = imaplib.IMAP4_SSL(imapserver)
|
||||||
|
imap.login(username, password)
|
||||||
|
|
||||||
|
status, messages = imap.select("Notes")
|
||||||
|
|
||||||
|
messages = int(messages[0])
|
||||||
|
|
||||||
|
for i in range(messages, messages-N, -1):
|
||||||
|
res, msg = imap.fetch(str(i), "(RFC822)")
|
||||||
|
for response in msg:
|
||||||
|
if isinstance(response, tuple):
|
||||||
|
msg = email.message_from_bytes(response[1])
|
||||||
|
subject, encoding = decode_header(msg["Subject"])[0]
|
||||||
|
if isinstance(subject, bytes):
|
||||||
|
subject = subject.decode(encoding)
|
||||||
|
|
||||||
|
From, encoding = decode_header(msg.get("From"))[0]
|
||||||
|
if isinstance(From, bytes):
|
||||||
|
From = From.decode(encoding)
|
||||||
|
|
||||||
|
print(subject)
|
||||||
|
filepath = clean(subject) + '.md'
|
||||||
|
filepath = os.path.join('notes', filepath)
|
||||||
|
|
||||||
|
if msg.is_multipart():
|
||||||
|
for part in msg.walk():
|
||||||
|
content_type = part.get_content_type()
|
||||||
|
content_disposition = str(part.get("Content-Disposition"))
|
||||||
|
try:
|
||||||
|
body = part.get_payload(decode=True).decode()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if content_type == "text/plain" and "attachment" not in content_disposition:
|
||||||
|
open(filepath, "w").write(body)
|
||||||
|
elif "attachment" in content_disposition:
|
||||||
|
print('/!\\ attachment')
|
||||||
|
else:
|
||||||
|
content_type = msg.get_content_type()
|
||||||
|
body = msg.get_payload(decode=True).decode()
|
||||||
|
if content_type == "text/plain":
|
||||||
|
open(filepath, "w").write(body)
|
||||||
|
|
||||||
|
if content_type == "text/html":
|
||||||
|
md = markdownify(body)
|
||||||
|
if md[:4] == 'html':
|
||||||
|
md = md[4:]
|
||||||
|
|
||||||
|
open(filepath, "wb").write(md.encode('utf8'))
|
||||||
|
|
||||||
|
imap.close()
|
||||||
|
imap.logout()
|
|
@ -0,0 +1,12 @@
|
||||||
|
From email Wed Apr 10 08:45:21 2024
|
||||||
|
From: name <email>
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain; charset="utf-8"
|
||||||
|
Date: Wed, 10 Apr 2024 02:45:21 -0400
|
||||||
|
Reply-To: name <email>
|
||||||
|
X-Uniform-Type-Identifier: com.apple.mail-note
|
||||||
|
Subject: title
|
||||||
|
X-Universally-Unique-Identifier: uid
|
||||||
|
Status: RO
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
rm mbox
|
||||||
|
for f in input/*.md
|
||||||
|
do
|
||||||
|
f=${f##*/}
|
||||||
|
title=${f%.md}
|
||||||
|
|
||||||
|
uid=$(cat /proc/sys/kernel/random/uuid)
|
||||||
|
cp imap-note-header "$title".imap
|
||||||
|
sed -i "s/uid/${uid}/" "$title".imap
|
||||||
|
sed -i "s/title/${title}/" "$title".imap
|
||||||
|
sed -i "s/name/$1/" "$title".imap
|
||||||
|
sed -i "s/email/$2/" "$title".imap
|
||||||
|
|
||||||
|
cat "input/$f" >> "$title".imap
|
||||||
|
cat "$title".imap >> mbox
|
||||||
|
printf '\n\n' >> mbox
|
||||||
|
rm "$title".imap
|
||||||
|
done
|
|
@ -0,0 +1,12 @@
|
||||||
|
Tool to create a mbox file from a set of markdown files
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
```bash
|
||||||
|
md2imap.sh <name> <email>
|
||||||
|
```
|
||||||
|
|
||||||
|
To import the mbox file to an imap server using mutt:
|
||||||
|
* Open mbox file: `mutt -f mbox`
|
||||||
|
* `T` then `.` to select all
|
||||||
|
* `;` then `s` to save to =Notes folder
|
||||||
|
* `U` then `.` to undelete mbox, if needed
|
Loading…
Reference in New Issue