-
Notifications
You must be signed in to change notification settings - Fork 0
/
bumblebee.ts
95 lines (80 loc) · 2.58 KB
/
bumblebee.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { Command, ensureDir, globToRegExp } from "./deps.ts";
import { IChange } from "./types.ts";
const IMAGE_URL_REGEXP = /!\[\w*\]\((\S*)\)/gm;
const DATE_REGEXP = /^date:\s*(\d{4})-(\d{1,2})-\d{1,2}/gm;
const getParams = () => {
const postPath = prompt(
"Where is the folder containing your blog posts located (using absolute paths)?",
"./",
)!;
const fex = prompt(
"What file extensions would you like to scan?",
"*.md",
)!;
const domain = prompt(
"Which is your new domain name (e.g. files.shaiwang.life)?",
);
return { postPath, fex, domain };
};
const download = async (url: string, folder: string, filename: string) => {
const response = await fetch(url);
const data = await response.arrayBuffer();
await ensureDir(folder);
return Deno.writeFile(`${folder}/${filename}`, new Uint8Array(data));
};
const edit = async (filename: string, content: string, changes: IChange[]) => {
const encoder = new TextEncoder();
const newContent = changes.reduce(
(acc, { old, new: newValue }) => acc.replaceAll(old, newValue),
content,
);
const data = encoder.encode(newContent);
await Deno.writeFile(filename, data, { create: false });
};
const appendZero = (num: number) => (num < 10 ? `0${num}` : `${num}`);
const migrate = async (filename: string, domain: string) => {
console.log(`Migrating ${filename}...`);
const content = await Deno.readTextFile(filename);
const dateMatch = [...content.matchAll(DATE_REGEXP)];
const year = appendZero(+dateMatch[0][1]);
const month = appendZero(+dateMatch[0][2]);
const urlMatches = content.matchAll(IMAGE_URL_REGEXP);
const changes: IChange[] = [];
for (const match of urlMatches) {
const imageURL = match[1];
const imageName = imageURL.slice(imageURL.lastIndexOf("/") + 1);
await download(
imageURL,
`./img/${year}/${month}`,
`${imageName}`,
);
if (domain) {
changes.push({
old: imageURL,
new: `https://${domain}/${year}/${month}/${imageName}`,
});
}
}
if (changes.length) {
await edit(filename, content, changes);
}
};
const bumblebee = async () => {
const { postPath, fex, domain } = getParams();
const regExp = globToRegExp(fex, {
extended: true,
globstar: true,
caseInsensitive: false,
});
for await (const { isFile, name } of Deno.readDir(postPath)) {
if (isFile && regExp.test(name)) {
await migrate(`${postPath}/${name}`, domain ?? "");
}
}
};
new Command()
.name("bumblebee")
.description("CLI for migrating blog post images")
.version("1.0.0")
.action(bumblebee)
.parse(Deno.args);