DEV Community

Cover image for How to export from Ulysses to Markdown
Emma Goto πŸ™
Emma Goto πŸ™

Posted on β€’ Originally published at emgoto.com on

5

How to export from Ulysses to Markdown

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.

  1. Right click a sheet in Ulysses and choose the Quick Export option. Choose the Textbundle format.
  2. Save the Textbundle folder to your desired location. I save it inside the scripts folder of my repository.
  3. 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();
Enter fullscreen mode Exit fullscreen mode

You can run the script directly with:

node ./scripts/ulysses.js
Enter fullscreen mode Exit fullscreen mode

Or you can add the script to your package.json file:

"scripts": {
    "uly": "./scripts/ulysses.js",
},
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The script will rearrange it to look like this:

posts
    ulysses-to-markdown
        text.md
        image.png
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more