将 Ghost 存储的博文导入到 Hugo 中
Page content
前置需求
本脚本使用 Node.js 写成,所以需要一个起码支持 ES6 module 的 Node 即可正常运行喵~
使用方式
- 新建一个目录;
- 将下列 文件列表 里的文件变成磁盘上的文件;
- 进入该目录, 执行
npm i
安装依赖库; - 执行
node .\index.mjs your-path-to\ghost.db [export_path]
即可喵~
已有功能
- 自动生成 YAML 格式的 Front Matter;
- 导出 Ghost 的 Tags 并写入 Front Matter;
- 自动格式化日期(时区是写死的东八区要注意喵!)
- 自动过滤标题转义符进行转义
- 按照
YYYY-MM\slug.md
的格式存储,不会一次性在目录下弄出大量文件也避免文件名冲突喵~
文件列表
index.mjs
import sqlite3 from "sqlite3";
import { open } from "sqlite";
import moment from "moment";
import process from "process";
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
if (process.argv.length < 3) {
console.log(
`Usage: ${process.argv[0]} ${process.argv[1]} sqlite_db.file [export_path]`
);
process.exit(1);
}
var content_path = "";
if (process.argv.length > 3) {
content_path = process.argv[3];
} else {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
content_path = path.join(__dirname, "content");
}
(async function main() {
const db = await open({
filename: process.argv[2],
driver: sqlite3.cached.Database,
});
await fs.mkdir(content_path, { recursive: true });
const tags = await db.all(`SELECT * from "tags"`);
let tag_map = {};
for (let tag of tags) {
tag_map[tag.id] = tag.name;
}
const posts = await db.all(`SELECT * from "posts"`);
const posts_tags = await db.all(`SELECT * from "posts_tags"`);
let post_tag_map = {};
for (let ptm of posts_tags) {
if (ptm.post_id in post_tag_map) {
post_tag_map[ptm.post_id].push(tag_map[ptm.tag_id]);
} else {
post_tag_map[ptm.post_id] = [tag_map[ptm.tag_id]];
}
}
for (const post of posts) {
const post_content = `---
title: "${post.title.replace(/\\/g, "\\\\")}"
date: ${moment(post.created_at).format(
moment.HTML5_FMT.DATETIME_LOCAL_SECONDS
)}+08:00
lastmod: ${moment(post.created_at).format(
moment.HTML5_FMT.DATETIME_LOCAL_SECONDS
)}+08:00
draft: ${post.status === "draft"}
isCJKLanguage: true
${
post.id in post_tag_map
? 'tags:\n - "' + post_tag_map[post.id].join('"\n - "') + '"\n'
: ""
}---
${post.markdown}`;
const post_path = path.join(
content_path,
`${moment(post.created_at).format("YYYY-MM")}`
);
const post_file = path.join(post_path, `${post.slug}.md`);
await fs.mkdir(post_path, { recursive: true });
await fs.writeFile(post_file, post_content);
}
})();
package.json
{
"name": "ghost-import-md",
"version": "1.0.0",
"description": "Import ghost blog posts to .md static files.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"dependencies": {
"moment": "^2.0.0",
"sqlite": "^4.0.23",
"sqlite3": "^5.0.2"
}
}