I mention in a (ok, the) previous post that I am enjoying using Joplin. It makes sense to write my blog posts in Joplin because it's a synced multiplatform offline text editing tool (with version history!). In addition, this blog is hosted on prose.sh, a really simple plain text blogging service where you just use ssh to dump markdown files into a directory. Fundamentally Joplin is just a markdown editor, so it didn't take long for me to start wondering if I could link the two together into a convenient workflow. Here's what I came up with and I'm pretty happy with the results.
When Joplin is running, it already has an excellent local rest-API for extracting (or creating) notes. They are already written in Markdown (as that is what Joplin uses natively) and so it was simply a matter of pulling out the note, converting the metadata (such as title, creation date etc) to the front matter format expected by prose.sh, and piping the result into ssh to deliver it to the blog.
One tweak is that I fiddle with links if they are internal to another note so that they point to a blog post with the same ID. I also pull in the tags and apply them to the post, but only if they begin with blog/ (which I remove) so that I can have a separate blog-specific tag namespace.
1res = api.get("/notes/#{opts.note_id}",
2 :params => { :token => opts.token,
3 :fields => "title,body,created_time,updated_time" })
4raise "failed to talk to joplin: #{res}" unless res.status.success?
5note = res.parse
6
7# ...
8
9begin
10 out.puts "---"
11 out.puts "title: #{note["title"]}"
12 out.puts "draft: true" if opts.draft
13 out.puts "date: #{opts.date}"
14 out.puts "---"
15 out.puts note_body
16ensure
17 out.close unless opts.debug
18end
(link to full script)
For the moment, I need to grab the note ID and pass it in as the command line arg. This is easily done as Joplin provides a handy copy button next to the note ID in the info panel. However, what I might do is make it automatically read all the notes from a certain folder and publish them to the blog, which would mean the script wouldn't require any input to do its thing.