I use the Ulysses text editor to write all my posts. Converting them into Markdown files for my blog isnβt as easy as copy-pasting, especially when things like frontmatter and images are involved.
So here's the script I use to convert Ulysses files to Markdown.
- Right click a sheet in Ulysses and choose the Quick Export option. Choose the Textbundle format.
- Save the Textbundle folder to your desired location. I save it inside the
scripts
folder of my repository. - Then run the following script to convert the Ulysses file to Markdown.
#!/usr/bin/env node
const { renameSync, unlink, rmdir } = require('fs');
const { join } = require('path');
const glob = require('glob');
const replace = require('replace-in-file');
const toFrontMatter = (title) =>
`---
title: "${title}"
date: ${new Date().toISOString().substring(0, 10)}
tags: []
---`;
const ulysses = async () => {
const file = glob.sync(
join(process.cwd(), 'scripts', '**', '*.textbundle'),
)[0];
// Moves the .textbundle file to the /posts directory
const slug = file.match(/\/([^\/]+).textbundle/)[1];
const postsDirectory = join(process.cwd(), 'posts');
let newFolder = `${postsDirectory}/${slug}`;
renameSync(file, newFolder);
// Move images out of assets folder
const images = glob.sync(join(newFolder, 'assets', '*'));
images.forEach((image) => {
let imageName = image.match(/assets\/([^\/]+)/)[1];
const newFolder = `${postsDirectory}/${slug}`;
renameSync(image, `${newFolder}/${imageName}`);
});
// Remove redundant folder and files
rmdir(`${newFolder}/assets`, () => {});
unlink(`${newFolder}/info.json`, () => {});
// Formats into frontmatter structure
const headerRegex = /^# .*/g;
const markdownPngRegex = /!\[.*\]\(assets.*png\)/g;
const headerFn = (title) =>
toFrontMatter(title.replace('# ', '').trim());
const markdownPngFn = (line) => line.replace(/\(assets/, '(.');
const options = {
files: `${newFolder}/index.mdx`,
from: [headerRegex, markdownPngRegex],
to: [headerFn, markdownPngFn],
};
return replace(options);
};
ulysess();
You can run the script directly with:
node ./scripts/ulysses.js
Or you can add the script to your package.json
file:
"scripts": {
"uly": "./scripts/ulysses.js",
},
And then run it with yarn uly
.
How the Ulysses to Markdown script works
Exporting a Ulysses file as a Textbundle saves it with the following file structure:
scripts
ulysses-to-markdown.textbundle
info.json
text.md
assets
image.png
The script will rearrange it to look like this:
posts
ulysses-to-markdown
text.md
image.png
The original Markdown file, directly from Ulysses, will look like this:
# How to export from Ulysses to Markdown
Here's the content of the post.
![](assets/image.png)
And the script will convert it into this format:
---
title: "How to export from Ulysses to Markdown"
date: 2021-09-25
tags: []
---
Here's the content of the post.
![](./image.png)
Top comments (0)