(config: ITranspilerConfig)
| 43 | } else if (concurrency < 1) { |
| 44 | concurrency = 1; |
| 45 | } |
| 46 | return pLimit(concurrency); |
| 47 | } |
| 48 | |
| 49 | // abapGit stores the content of a Web Repository or MIME object beside its |
| 50 | // XML, in a file whose name says .w3mi.data. or .smim.data. That content is |
| 51 | // bytes, and reading it as UTF-8 destroys it: every byte above 0x7F fails to |
| 52 | // decode and comes back as the replacement character, so a PNG arrives |
| 53 | // starting ef bf bd rather than 89 50 4e 47 and is served, with a plausible |
| 54 | // size and the right content type, as a broken image. |
| 55 | // |
| 56 | // latin1 rather than a Buffer because the whole pipeline carries a file as a |
| 57 | // string; latin1 maps every byte to the code point of the same value, so a |
| 58 | // read and a write of it are exact. Node's "binary" is the same encoding |
| 59 | // under its old name, so there is nothing more faithful to switch to: the |
| 60 | // only stronger answer is to carry a Buffer end to end and never make it a |
| 61 | // string at all, which is a change to every file the transpiler touches. |
| 62 | // Measured on an 11770 byte PNG: latin1 and binary both return it |
| 63 | // unchanged, utf8 returns 20175 bytes and no longer a PNG. |
| 64 | public static isBinaryFilename(filename: string): boolean { |
| 65 | return /\.(w3mi|smim)\.data\./i.test(filename); |
| 66 | } |
| 67 | |
| 68 | public static async readAllFiles(filesToRead: string[], outputFolder: string) { |
| 69 | const limit = this.setupPLimit(); |
| 70 | const promises = filesToRead.map((filename) => { |
| 71 | return limit(async () => { |
| 72 | return { |
| 73 | filename: path.basename(filename), |
| 74 | relative: path.relative(outputFolder, path.dirname(filename)), |
| 75 | contents: await fsPromises.readFile(filename, this.isBinaryFilename(filename) ? "latin1" : "utf8"), |
no test coverage detected