|
| 1 | +const fs = require("fs"); |
| 2 | +const path = require("path"); |
| 3 | + |
1 | 4 | const chalk = require("chalk");
|
| 5 | +const got = require("got"); |
2 | 6 |
|
3 | 7 | const { Document, Redirect } = require("../content");
|
4 | 8 | const { FLAW_LEVELS } = require("./constants");
|
|
7 | 11 | findMatchesInText,
|
8 | 12 | replaceMatchesInText,
|
9 | 13 | } = require("./matches-in-text");
|
| 14 | +const { fstat } = require("fs-extra"); |
10 | 15 |
|
11 | 16 | function injectFlaws(doc, $, options, { rawContent }) {
|
12 | 17 | if (doc.isArchive) return;
|
@@ -169,7 +174,7 @@ function injectFlaws(doc, $, options, { rawContent }) {
|
169 | 174 | }
|
170 | 175 | }
|
171 | 176 |
|
172 |
| -function fixFixableFlaws(doc, options, document) { |
| 177 | +async function fixFixableFlaws(doc, options, document) { |
173 | 178 | if (!options.fixFlaws || document.isArchive) return;
|
174 | 179 |
|
175 | 180 | let newRawHTML = document.rawHTML;
|
@@ -229,27 +234,52 @@ function fixFixableFlaws(doc, options, document) {
|
229 | 234 | }
|
230 | 235 | }
|
231 | 236 |
|
232 |
| - // Any 'images' flaws with a suggestion... |
| 237 | + // Any 'images' flaws with a suggestion or external image... |
233 | 238 | for (const flaw of doc.flaws.images || []) {
|
234 |
| - if (!flaw.suggestion) { |
| 239 | + if (!(flaw.suggestion || flaw.externalImage)) { |
235 | 240 | continue;
|
236 | 241 | }
|
237 | 242 | // The reason we're not using the parse HTML, as a cheerio object `$`
|
238 | 243 | // is because the raw HTML we're dealing with isn't actually proper
|
239 | 244 | // HTML. It's only proper HTML when the kumascript macros have been
|
240 | 245 | // expanded.
|
241 | 246 | const htmlBefore = newRawHTML;
|
242 |
| - newRawHTML = replaceMatchesInText(flaw.src, newRawHTML, flaw.suggestion, { |
| 247 | + let newSrc; |
| 248 | + if (flaw.externalImage) { |
| 249 | + // Sanity check that it's an external image |
| 250 | + const url = new URL(flaw.src); |
| 251 | + if (url.protocol !== "https:") { |
| 252 | + throw new Error(`Insecure image URL ${flaw.src}`); |
| 253 | + } |
| 254 | + try { |
| 255 | + const imageBuffer = await got(flaw.src, { |
| 256 | + responseType: "buffer", |
| 257 | + resolveBodyOnly: true, |
| 258 | + timeout: 10000, |
| 259 | + retry: 3, |
| 260 | + }); |
| 261 | + const destination = path.join( |
| 262 | + Document.getFolderPath(document.metadata), |
| 263 | + path.basename(url.pathname) |
| 264 | + ); |
| 265 | + fs.writeFileSync(destination, imageBuffer); |
| 266 | + console.log(`Downloaded ${flaw.src} to ${destination}`); |
| 267 | + newSrc = path.basename(destination); |
| 268 | + } catch (error) { |
| 269 | + console.error(error); |
| 270 | + throw error; |
| 271 | + } |
| 272 | + } else { |
| 273 | + newSrc = flaw.suggestion; |
| 274 | + } |
| 275 | + newRawHTML = replaceMatchesInText(flaw.src, newRawHTML, newSrc, { |
243 | 276 | inAttribute: "src",
|
244 | 277 | });
|
245 |
| - if (htmlBefore !== newRawHTML) { |
246 |
| - // flaw.fixed = !options.fixFlawsDryRun; |
247 |
| - } |
248 | 278 | if (loud) {
|
249 | 279 | console.log(
|
250 | 280 | chalk.grey(
|
251 | 281 | `Fixed image ${chalk.white.bold(flaw.src)} to ${chalk.white.bold(
|
252 |
| - flaw.suggestion |
| 282 | + newSrc |
253 | 283 | )}`
|
254 | 284 | )
|
255 | 285 | );
|
|
0 commit comments