Skip to content

Instantly share code, notes, and snippets.

@ephbaum
Created October 10, 2023 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ephbaum/286b9d0c0fb9941a525d6dfdd7307b08 to your computer and use it in GitHub Desktop.
Save ephbaum/286b9d0c0fb9941a525d6dfdd7307b08 to your computer and use it in GitHub Desktop.
Ghost Blog backup to Astro markdown - The Hard Way
const fs = require('fs');
fs.readFile('./data/backfile.json', 'utf8', (err, data) => {
if (err) throw err;
const backup = JSON.parse(data);
processBackup(backup);
});
function processBackup(backup) {
const posts = backup.db[0].data.posts;
for (let i = 0; i < posts.length; i++) {
const post = posts[i];
const {
title,
html,
feature_image,
slug: postSlug,
published_at: pubDatetime
} = post;
const markdown = convertHtmlToMarkdown(html);
const metadata = {
title,
feature_image,
postSlug,
pubDatetime
};
saveAsMarkdownFile(title, markdown, metadata);
}
}
const TurndownService = require('turndown');
const turndown = new TurndownService();
function convertHtmlToMarkdown(html) {
return turndown.turndown(html);
}
function slugify(str) {
return str
.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/[\/?…]+/g, '-') // Replace forward slashes, question marks, and ellipses with hyphens
.replace(/-+/g, '-') // Replace multiple hyphens with a single hyphen
.replace(/[^a-z0-9-]/g, ''); // Remove any remaining characters that are not alphanumeric or hyphens
}
function replaceGhostUrlPlaceholders(str) {
// Remove __GHOST_URL__ from URLs
let updatedStr = str.replace(/__GHOST_URL__\//g, '/');
// Change /content/images to /assets/images
updatedStr = updatedStr.replace(/\/content\/images/g, '../../assets/images');
return updatedStr;
}
function saveAsMarkdownFile(title, markdown, metadata) {
const pubDate = new Date(metadata.pubDatetime);
const formattedDate = pubDate.toISOString().split('T')[0]; // Formats date as YYYY-MM-DD
const fileName = `${formattedDate}-${slugify(title)}.md`;
if (metadata.feature_image) { // convert feature image to ogImage, if it exists
metadata.feature_image = replaceGhostUrlPlaceholders(metadata.feature_image);
metadata.ogImage = metadata.feature_image;
} else { // otherwise just delete this key
delete metadata.feature_image;
}
// add an image tage for the featured image
const imageMarkdown = metadata.feature_image ? `![Featured Image](${metadata.feature_image})\n\n` : '';
delete metadata.feature_image;
const updatedMarkdown = replaceGhostUrlPlaceholders(markdown);
const metadataUpdated = Object.entries(metadata)
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
const content = `---
${metadataUpdated}
featured: false
draft: false
tags:
- relevant-tag
description:
Placeholder description for imported post from Ghost Blog
---
${imageMarkdown}${updatedMarkdown}
`;
fs.writeFile(`./output/${fileName}`, content, err => {
if (err) throw err;
});
}
{
"dependencies": {
"turndown": "^7.1.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment