rehype-og-card 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +36 -14
- package/dist/util/cache.d.ts +18 -3
- package/dist/util/cache.js +44 -6
- package/dist/util/file.d.ts +20 -2
- package/dist/util/file.js +51 -9
- package/dist/util/network.d.ts +3 -3
- package/dist/util/network.js +10 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Rehype plugin to convert text links to link cards inspired by [remark-link-card]
|
|
|
10
10
|
| Shorten URLs displayed on link cards | ✅ | ✅ |
|
|
11
11
|
| Server-side cache for images | ✅ | ✅ |
|
|
12
12
|
| Cache images with long URLs | ❌ ([implemented](https://github.com/gladevise/remark-link-card/pull/16) but not released) | ✅ |
|
|
13
|
-
| Build cache for Open Graph metadata and images | ❌ |
|
|
13
|
+
| Build cache for Open Graph metadata and images | ❌ | ✅ |
|
|
14
14
|
| Exclude links in lists from conversion | ❌ | ✅ |
|
|
15
15
|
| Exclude specific domains from conversion | ❌ | ✅ |
|
|
16
16
|
| Lazy loading images | ❌ | ✅ |
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { convertTextToAnchorElement, createOGCard, isAnchorElement, isTextNode } from "./util/hast.js";
|
|
11
|
+
import { checkFileExistsSync, createDirectorySync } from "./util/file.js";
|
|
11
12
|
import { downloadImage, getOGData, isValidURL } from "./util/network.js";
|
|
12
|
-
import { restoreBuildCache,
|
|
13
|
+
import { restoreBuildCache, restoreOGDataBuildCache, saveBuildCacheFile, saveOGDataBuildCache } from "./util/cache.js";
|
|
13
14
|
import { isElement } from "hast-util-is-element";
|
|
14
15
|
import path from "path";
|
|
15
16
|
import { visitParents } from "unist-util-visit-parents";
|
|
@@ -32,7 +33,7 @@ const DEFAULT_OPTIONS = {
|
|
|
32
33
|
* @param options Plugin options.
|
|
33
34
|
* @returns Transformer function.
|
|
34
35
|
*/
|
|
35
|
-
// eslint-disable-next-line max-lines-per-function
|
|
36
|
+
// eslint-disable-next-line max-lines-per-function, max-statements
|
|
36
37
|
const rehypeOGCard = (options) => {
|
|
37
38
|
const mergedOptions = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
|
|
38
39
|
if (mergedOptions.buildCache && !mergedOptions.serverCache) {
|
|
@@ -40,15 +41,21 @@ const rehypeOGCard = (options) => {
|
|
|
40
41
|
}
|
|
41
42
|
mergedOptions.serverCachePath = path.posix.join(mergedOptions.serverCachePath, "./rehype-og-card/");
|
|
42
43
|
mergedOptions.buildCachePath = path.posix.join(mergedOptions.buildCachePath, "./rehype-og-card/");
|
|
44
|
+
const buildCacheExists = checkFileExistsSync(mergedOptions.buildCachePath);
|
|
45
|
+
if (mergedOptions.buildCache) {
|
|
46
|
+
if (buildCacheExists) {
|
|
47
|
+
restoreBuildCache(mergedOptions.buildCachePath, mergedOptions.serverCachePath);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
createDirectorySync(mergedOptions.buildCachePath);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
43
53
|
/**
|
|
44
54
|
* Transform function to create OG card from bare links.
|
|
45
55
|
* @param tree Root node of the HAST tree.
|
|
46
56
|
*/
|
|
47
57
|
// eslint-disable-next-line max-lines-per-function
|
|
48
58
|
const transform = (tree) => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
-
if (mergedOptions.buildCache) {
|
|
50
|
-
yield restoreBuildCache(mergedOptions.buildCachePath, mergedOptions.serverCachePath);
|
|
51
|
-
}
|
|
52
59
|
const linkCardPromises = [];
|
|
53
60
|
// eslint-disable-next-line max-statements, max-lines-per-function
|
|
54
61
|
visitParents(tree, ["element", "text"], (node, ancestors) => {
|
|
@@ -85,30 +92,48 @@ const rehypeOGCard = (options) => {
|
|
|
85
92
|
const targetURL = new URL(anchorNode.properties.href);
|
|
86
93
|
if ((_a = mergedOptions.excludeDomains) === null || _a === void 0 ? void 0 : _a.includes(targetURL.hostname))
|
|
87
94
|
return;
|
|
88
|
-
// eslint-disable-next-line jsdoc/require-jsdoc, max-statements
|
|
95
|
+
// eslint-disable-next-line jsdoc/require-jsdoc, max-statements, max-lines-per-function
|
|
89
96
|
const linkCardPromise = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
let OGData = mergedOptions.buildCache
|
|
98
|
+
? yield restoreOGDataBuildCache(anchorNode.properties.href, mergedOptions.buildCachePath)
|
|
99
|
+
: null;
|
|
100
|
+
if (!OGData) {
|
|
101
|
+
OGData = yield getOGData(anchorNode.properties.href, mergedOptions.crawlerUserAgent);
|
|
102
|
+
if (!OGData)
|
|
103
|
+
return;
|
|
104
|
+
if (mergedOptions.buildCache) {
|
|
105
|
+
yield saveOGDataBuildCache(anchorNode.properties.href, OGData, mergedOptions.buildCachePath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
93
108
|
if (OGData.OGImageURL && mergedOptions.serverCache) {
|
|
94
109
|
const filename = yield downloadImage({
|
|
95
|
-
|
|
110
|
+
directory: mergedOptions.serverCachePath,
|
|
96
111
|
url: OGData.OGImageURL,
|
|
97
112
|
userAgent: mergedOptions.crawlerUserAgent
|
|
98
113
|
});
|
|
99
114
|
if (filename && mergedOptions.serverCache) {
|
|
100
115
|
OGData.OGImageURL = path.posix.join("/rehype-og-card", filename);
|
|
101
116
|
}
|
|
117
|
+
if (filename && mergedOptions.buildCache) {
|
|
118
|
+
const downloadedFilePath = path.join(mergedOptions.serverCachePath, filename);
|
|
119
|
+
const buildCachePath = path.join(mergedOptions.buildCachePath, filename);
|
|
120
|
+
yield saveBuildCacheFile(downloadedFilePath, buildCachePath);
|
|
121
|
+
}
|
|
102
122
|
}
|
|
103
123
|
if (OGData.faviconURL && mergedOptions.serverCache) {
|
|
104
124
|
const filename = yield downloadImage({
|
|
105
|
-
|
|
125
|
+
directory: mergedOptions.serverCachePath,
|
|
106
126
|
url: OGData.faviconURL,
|
|
107
127
|
userAgent: mergedOptions.crawlerUserAgent
|
|
108
128
|
});
|
|
109
129
|
if (filename && mergedOptions.serverCache) {
|
|
110
130
|
OGData.faviconURL = path.posix.join("/rehype-og-card", filename);
|
|
111
131
|
}
|
|
132
|
+
if (filename && mergedOptions.buildCache) {
|
|
133
|
+
const downloadedFilePath = path.join(mergedOptions.serverCachePath, filename);
|
|
134
|
+
const buildCachePath = path.join(mergedOptions.buildCachePath, filename);
|
|
135
|
+
yield saveBuildCacheFile(downloadedFilePath, buildCachePath);
|
|
136
|
+
}
|
|
112
137
|
}
|
|
113
138
|
if (mergedOptions.shortenURL) {
|
|
114
139
|
const shortenedURL = new URL(anchorNode.properties.href);
|
|
@@ -126,9 +151,6 @@ const rehypeOGCard = (options) => {
|
|
|
126
151
|
linkCardPromises.push(linkCardPromise());
|
|
127
152
|
});
|
|
128
153
|
yield Promise.all(linkCardPromises);
|
|
129
|
-
if (mergedOptions.buildCache) {
|
|
130
|
-
yield saveBuildCache(mergedOptions.serverCachePath, mergedOptions.buildCachePath);
|
|
131
|
-
}
|
|
132
154
|
});
|
|
133
155
|
return transform;
|
|
134
156
|
};
|
package/dist/util/cache.d.ts
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
|
+
import { OGCardData } from "../types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Save build cache if server cache exists.
|
|
3
4
|
* @param serverCachePath Server cache path.
|
|
4
5
|
* @param buildCachePath Build cache path.
|
|
5
6
|
*/
|
|
6
|
-
declare const
|
|
7
|
+
declare const saveBuildCacheFile: (serverCachePath: string, buildCachePath: string) => Promise<void>;
|
|
7
8
|
/**
|
|
8
9
|
* Restore build cache if it exists.
|
|
9
10
|
* @param buildCachePath Build cache path.
|
|
10
11
|
* @param serverCachePath Server cache path.
|
|
11
12
|
*/
|
|
12
|
-
declare const restoreBuildCache: (buildCachePath: string, serverCachePath: string) =>
|
|
13
|
-
|
|
13
|
+
declare const restoreBuildCache: (buildCachePath: string, serverCachePath: string) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Save OG data to build cache.
|
|
16
|
+
* @param url URL of the OG data.
|
|
17
|
+
* @param OGData OG data to save.
|
|
18
|
+
* @param buildCachePath Build cache path.
|
|
19
|
+
*/
|
|
20
|
+
declare const saveOGDataBuildCache: (url: string, OGData: OGCardData, buildCachePath: string) => Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Restore OG data from build cache.
|
|
23
|
+
* @param url URL of the OG data.
|
|
24
|
+
* @param buildCachePath Build cache path.
|
|
25
|
+
* @returns Restored OG data. If not found, returns `null`.
|
|
26
|
+
*/
|
|
27
|
+
declare const restoreOGDataBuildCache: (url: string, buildCachePath: string) => Promise<OGCardData | null>;
|
|
28
|
+
export { saveBuildCacheFile, restoreBuildCache, saveOGDataBuildCache, restoreOGDataBuildCache };
|
package/dist/util/cache.js
CHANGED
|
@@ -7,21 +7,59 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { copyDirectory } from "./file.js";
|
|
10
|
+
import { checkFileExists, copyDirectory, generateFilename } from "./file.js";
|
|
11
|
+
import fs from "fs/promises";
|
|
12
|
+
import path from "path";
|
|
11
13
|
/**
|
|
12
14
|
* Save build cache if server cache exists.
|
|
13
15
|
* @param serverCachePath Server cache path.
|
|
14
16
|
* @param buildCachePath Build cache path.
|
|
15
17
|
*/
|
|
16
|
-
const
|
|
17
|
-
yield
|
|
18
|
+
const saveBuildCacheFile = (serverCachePath, buildCachePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
const serverCacheExists = yield checkFileExists(serverCachePath);
|
|
20
|
+
const buildCacheExists = yield checkFileExists(buildCachePath);
|
|
21
|
+
if (serverCacheExists && !buildCacheExists) {
|
|
22
|
+
yield fs.copyFile(serverCachePath, buildCachePath);
|
|
23
|
+
}
|
|
18
24
|
});
|
|
19
25
|
/**
|
|
20
26
|
* Restore build cache if it exists.
|
|
21
27
|
* @param buildCachePath Build cache path.
|
|
22
28
|
* @param serverCachePath Server cache path.
|
|
23
29
|
*/
|
|
24
|
-
const restoreBuildCache = (buildCachePath, serverCachePath) =>
|
|
25
|
-
|
|
30
|
+
const restoreBuildCache = (buildCachePath, serverCachePath) => {
|
|
31
|
+
copyDirectory(buildCachePath, serverCachePath);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Save OG data to build cache.
|
|
35
|
+
* @param url URL of the OG data.
|
|
36
|
+
* @param OGData OG data to save.
|
|
37
|
+
* @param buildCachePath Build cache path.
|
|
38
|
+
*/
|
|
39
|
+
const saveOGDataBuildCache = (url, OGData, buildCachePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const filename = generateFilename(url, false);
|
|
41
|
+
const savePath = `${path.join(buildCachePath, filename)}.json`;
|
|
42
|
+
const cacheDirectoryExists = yield checkFileExists(buildCachePath);
|
|
43
|
+
if (!cacheDirectoryExists) {
|
|
44
|
+
yield fs.mkdir(buildCachePath, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
yield fs.writeFile(savePath, JSON.stringify(OGData));
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* Restore OG data from build cache.
|
|
50
|
+
* @param url URL of the OG data.
|
|
51
|
+
* @param buildCachePath Build cache path.
|
|
52
|
+
* @returns Restored OG data. If not found, returns `null`.
|
|
53
|
+
*/
|
|
54
|
+
const restoreOGDataBuildCache = (url, buildCachePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
const filename = generateFilename(url, false);
|
|
56
|
+
const savePath = `${path.join(buildCachePath, filename)}.json`;
|
|
57
|
+
try {
|
|
58
|
+
const data = yield fs.readFile(savePath, "utf-8");
|
|
59
|
+
return JSON.parse(data);
|
|
60
|
+
}
|
|
61
|
+
catch (_a) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
26
64
|
});
|
|
27
|
-
export {
|
|
65
|
+
export { saveBuildCacheFile, restoreBuildCache, saveOGDataBuildCache, restoreOGDataBuildCache };
|
package/dist/util/file.d.ts
CHANGED
|
@@ -4,10 +4,28 @@
|
|
|
4
4
|
* @returns `true` if the file exists, `false` otherwise.
|
|
5
5
|
*/
|
|
6
6
|
declare const checkFileExists: (filePath: string) => Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Check if the file exists.
|
|
9
|
+
* @param filePath Path to check.
|
|
10
|
+
* @returns `true` if the file exists, `false` otherwise.
|
|
11
|
+
*/
|
|
12
|
+
declare const checkFileExistsSync: (filePath: string) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Create directory.
|
|
15
|
+
* @param dir Directory path.
|
|
16
|
+
*/
|
|
17
|
+
declare const createDirectorySync: (dir: string) => void;
|
|
7
18
|
/**
|
|
8
19
|
* Copy directory from source to destination.
|
|
9
20
|
* @param source Source directory.
|
|
10
21
|
* @param destination Destination directory.
|
|
11
22
|
*/
|
|
12
|
-
declare const copyDirectory: (source: string, destination: string) =>
|
|
13
|
-
|
|
23
|
+
declare const copyDirectory: (source: string, destination: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Generate filename from URL.
|
|
26
|
+
* @param url URL to generate filename.
|
|
27
|
+
* @param extension Include extension in the filename.
|
|
28
|
+
* @returns Generated filename.
|
|
29
|
+
*/
|
|
30
|
+
declare const generateFilename: (url: string, extension?: boolean) => string;
|
|
31
|
+
export { checkFileExists, checkFileExistsSync, createDirectorySync, copyDirectory, generateFilename };
|
package/dist/util/file.js
CHANGED
|
@@ -7,7 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import
|
|
10
|
+
import { createHash } from "crypto";
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
11
13
|
/**
|
|
12
14
|
* Check if the file exists.
|
|
13
15
|
* @param filePath Path to check.
|
|
@@ -15,26 +17,66 @@ import fs from "fs/promises";
|
|
|
15
17
|
*/
|
|
16
18
|
const checkFileExists = (filePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
19
|
try {
|
|
18
|
-
yield fs.access(filePath);
|
|
20
|
+
yield fs.promises.access(filePath);
|
|
19
21
|
return true;
|
|
20
22
|
}
|
|
21
23
|
catch (_a) {
|
|
22
24
|
return false;
|
|
23
25
|
}
|
|
24
26
|
});
|
|
27
|
+
/**
|
|
28
|
+
* Check if the file exists.
|
|
29
|
+
* @param filePath Path to check.
|
|
30
|
+
* @returns `true` if the file exists, `false` otherwise.
|
|
31
|
+
*/
|
|
32
|
+
const checkFileExistsSync = (filePath) => {
|
|
33
|
+
let result = false;
|
|
34
|
+
fs.access(filePath, (error) => {
|
|
35
|
+
result = !error;
|
|
36
|
+
});
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Create directory.
|
|
41
|
+
* @param dir Directory path.
|
|
42
|
+
*/
|
|
43
|
+
const createDirectorySync = (dir) => {
|
|
44
|
+
fs.mkdir(dir, { recursive: true }, (error) => {
|
|
45
|
+
if (error) {
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.error("[rehype-og-card] Failed to copy files: ", error);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
25
51
|
/**
|
|
26
52
|
* Copy directory from source to destination.
|
|
27
53
|
* @param source Source directory.
|
|
28
54
|
* @param destination Destination directory.
|
|
29
55
|
*/
|
|
30
|
-
const copyDirectory = (source, destination) =>
|
|
31
|
-
const sourceExists =
|
|
56
|
+
const copyDirectory = (source, destination) => {
|
|
57
|
+
const sourceExists = checkFileExistsSync(source);
|
|
32
58
|
if (!sourceExists)
|
|
33
59
|
return;
|
|
34
|
-
const destinationExists =
|
|
60
|
+
const destinationExists = checkFileExistsSync(destination);
|
|
35
61
|
if (!destinationExists) {
|
|
36
|
-
|
|
62
|
+
createDirectorySync(destination);
|
|
37
63
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
fs.cp(source, destination, { recursive: true }, (error) => {
|
|
65
|
+
if (error) {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.error("[rehype-og-card] Failed to copy files: ", error);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Generate filename from URL.
|
|
73
|
+
* @param url URL to generate filename.
|
|
74
|
+
* @param extension Include extension in the filename.
|
|
75
|
+
* @returns Generated filename.
|
|
76
|
+
*/
|
|
77
|
+
const generateFilename = (url, extension = true) => {
|
|
78
|
+
const hash = createHash("sha256").update(url).digest("hex");
|
|
79
|
+
const filename = extension ? hash + path.extname(new URL(url).pathname) : hash;
|
|
80
|
+
return filename;
|
|
81
|
+
};
|
|
82
|
+
export { checkFileExists, checkFileExistsSync, createDirectorySync, copyDirectory, generateFilename };
|
package/dist/util/network.d.ts
CHANGED
|
@@ -20,16 +20,16 @@ interface DownloadImageOptions {
|
|
|
20
20
|
/**
|
|
21
21
|
* Directory to save the downloaded image.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
directory: string;
|
|
24
24
|
/**
|
|
25
25
|
* User agent to use for fetching the image.
|
|
26
26
|
*/
|
|
27
27
|
userAgent: string;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* Download image from given URL.
|
|
30
|
+
* Download image from given URL. If the image already exists, return the filename.
|
|
31
31
|
* @param options Options to download image.
|
|
32
|
-
* @returns
|
|
32
|
+
* @returns Filename of the downloaded image.
|
|
33
33
|
*/
|
|
34
34
|
declare const downloadImage: (options: DownloadImageOptions) => Promise<string | null>;
|
|
35
35
|
export { isValidURL, getOGData, downloadImage };
|
package/dist/util/network.js
CHANGED
|
@@ -7,8 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { checkFileExists } from "./file.js";
|
|
11
|
-
import { createHash } from "crypto";
|
|
10
|
+
import { checkFileExists, generateFilename } from "./file.js";
|
|
12
11
|
import fs from "fs/promises";
|
|
13
12
|
import path from "path";
|
|
14
13
|
import scraper from "open-graph-scraper";
|
|
@@ -67,9 +66,9 @@ const getOGData = (url, userAgent) => __awaiter(void 0, void 0, void 0, function
|
|
|
67
66
|
}
|
|
68
67
|
});
|
|
69
68
|
/**
|
|
70
|
-
* Download image from given URL.
|
|
69
|
+
* Download image from given URL. If the image already exists, return the filename.
|
|
71
70
|
* @param options Options to download image.
|
|
72
|
-
* @returns
|
|
71
|
+
* @returns Filename of the downloaded image.
|
|
73
72
|
*/
|
|
74
73
|
// eslint-disable-next-line max-statements
|
|
75
74
|
const downloadImage = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -79,14 +78,12 @@ const downloadImage = (options) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
79
78
|
return null;
|
|
80
79
|
}
|
|
81
80
|
try {
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
const savePath = path.posix.join(options.directly, filename);
|
|
81
|
+
const filename = generateFilename(options.url);
|
|
82
|
+
const savePath = path.posix.join(options.directory, filename);
|
|
85
83
|
// If the file already exists, return the filename.
|
|
86
84
|
const fileExists = yield checkFileExists(savePath);
|
|
87
|
-
if (fileExists)
|
|
85
|
+
if (fileExists)
|
|
88
86
|
return filename;
|
|
89
|
-
}
|
|
90
87
|
const response = yield fetch(options.url, {
|
|
91
88
|
headers: {
|
|
92
89
|
"user-agent": options.userAgent
|
|
@@ -94,7 +91,10 @@ const downloadImage = (options) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
94
91
|
});
|
|
95
92
|
const arrayBuffer = yield response.arrayBuffer();
|
|
96
93
|
const buffer = Buffer.from(arrayBuffer);
|
|
97
|
-
yield
|
|
94
|
+
const saveDirectoryExists = yield checkFileExists(options.directory);
|
|
95
|
+
if (!saveDirectoryExists) {
|
|
96
|
+
yield fs.mkdir(options.directory, { recursive: true });
|
|
97
|
+
}
|
|
98
98
|
yield fs.writeFile(savePath, buffer);
|
|
99
99
|
return filename;
|
|
100
100
|
}
|