|
| 1 | +import {minimatch} from 'minimatch'; |
1 | 2 | import fs from 'node:fs/promises'; |
2 | 3 | import {createReadStream, createWriteStream} from 'node:fs'; |
3 | 4 | import {pipeline} from 'node:stream/promises'; |
@@ -42,61 +43,102 @@ const fileCache = new FileCache(); |
42 | 43 | const assets = new Map(); |
43 | 44 | const writtenAssets = new Set(); |
44 | 45 |
|
45 | | -async function processDirectory(pathToDir) { |
46 | | - for (const inputFile of await fs.readdir(pathToDir, {withFileTypes: true})) { |
47 | | - if (inputFile.isDirectory()) { |
48 | | - await processDirectory(path.join(pathToDir, inputFile.name)); |
49 | | - continue; |
50 | | - } |
| 46 | +/** |
| 47 | + * @param {string} pathToDir |
| 48 | + * @param {Dirent} inputFile |
| 49 | + */ |
| 50 | +async function processFile(pathToDir, inputFile) { |
| 51 | + const ext = path.extname(inputFile.name); |
51 | 52 |
|
52 | | - const ext = path.extname(inputFile.name); |
| 53 | + const pathToInput = path.join(pathToDir, inputFile.name); |
| 54 | + const pathToOutputDir = path.join(outputDir, path.relative(inputDir, pathToDir)); |
53 | 55 |
|
54 | | - if (!processable.has(ext) || isTemplate(inputFile.name)) { |
| 56 | + console.log('processing', pathToInput); |
| 57 | + const fileContents = await fileCache.get(pathToInput); |
| 58 | + |
| 59 | + const vFile = await processDocument({ |
| 60 | + inputFile: { |
| 61 | + name: pathToInput, |
| 62 | + text: fileContents |
| 63 | + }, |
| 64 | + assets, |
| 65 | + skipImageOptimization, |
| 66 | + fileCache, |
| 67 | + writtenAssets, |
| 68 | + outputDir: pathToOutputDir |
| 69 | + }); |
| 70 | + |
| 71 | + await ensureDirectory(pathToOutputDir); |
| 72 | + |
| 73 | + for (const [pathToOldAsset, pathToNewAsset] of assets) { |
| 74 | + if (writtenAssets.has(pathToNewAsset)) { |
55 | 75 | continue; |
56 | 76 | } |
57 | 77 |
|
58 | | - const pathToInput = path.join(pathToDir, inputFile.name); |
59 | | - const pathToOutputDir = path.join(outputDir, path.relative(inputDir, pathToDir)); |
| 78 | + await ensureDirectory(path.dirname(pathToNewAsset)); |
60 | 79 |
|
61 | | - console.log('processing', pathToInput); |
62 | | - const fileContents = await fileCache.get(pathToInput); |
| 80 | + console.log('write', pathToNewAsset); |
63 | 81 |
|
64 | | - const vFile = await processDocument({ |
65 | | - inputFile: { |
66 | | - name: pathToInput, |
67 | | - text: fileContents |
68 | | - }, |
69 | | - assets, |
70 | | - skipImageOptimization, |
71 | | - fileCache, |
72 | | - writtenAssets, |
73 | | - outputDir: pathToOutputDir |
74 | | - }); |
| 82 | + await pipeline( |
| 83 | + createReadStream(pathToOldAsset), |
| 84 | + createWriteStream(pathToNewAsset) |
| 85 | + ); |
75 | 86 |
|
76 | | - await ensureDirectory(pathToOutputDir); |
| 87 | + writtenAssets.add(pathToNewAsset); |
| 88 | + } |
77 | 89 |
|
78 | | - for (const [pathToOldAsset, pathToNewAsset] of assets) { |
79 | | - if (writtenAssets.has(pathToNewAsset)) { |
80 | | - continue; |
81 | | - } |
| 90 | + const outputName = `${path.basename(inputFile.name, ext)}.html`; |
| 91 | + const pathToOutput = path.join(pathToOutputDir, outputName); |
82 | 92 |
|
83 | | - await ensureDirectory(path.dirname(pathToNewAsset)); |
| 93 | + console.log('write', pathToOutput); |
| 94 | + await fs.writeFile(pathToOutput, String(vFile), 'utf8'); |
| 95 | +} |
84 | 96 |
|
85 | | - console.log('write', pathToNewAsset); |
| 97 | +const toCopy = [ |
| 98 | + '**/*.ttf', |
| 99 | + 'static/**/*.js', |
| 100 | + 'CNAME', |
| 101 | + 'favicon.io', |
| 102 | +]; |
| 103 | + |
| 104 | +/** |
| 105 | + * @param {string} pathToDir |
| 106 | + * @param {Dirent} inputFile |
| 107 | + */ |
| 108 | +async function copyFile(pathToDir, inputFile) { |
| 109 | + const pathToInput = path.join(pathToDir, inputFile.name); |
| 110 | + const relativeToInput = path.relative(inputDir, pathToInput); |
| 111 | + |
| 112 | + const copyable = toCopy.some(glob => minimatch(relativeToInput, glob)); |
| 113 | + |
| 114 | + if (!copyable) { |
| 115 | + return; |
| 116 | + } |
| 117 | + |
| 118 | + const pathToOutputDir = path.join(outputDir, path.relative(inputDir, pathToDir)); |
| 119 | + |
| 120 | + await ensureDirectory(pathToOutputDir); |
86 | 121 |
|
87 | | - await pipeline( |
88 | | - createReadStream(pathToOldAsset), |
89 | | - createWriteStream(pathToNewAsset) |
90 | | - ); |
| 122 | + const pathToOutput = path.join(pathToOutputDir, inputFile.name); |
91 | 123 |
|
92 | | - writtenAssets.add(pathToNewAsset); |
| 124 | + console.log('copy', pathToOutput); |
| 125 | + await fs.copyFile(pathToInput, pathToOutput); |
| 126 | +} |
| 127 | + |
| 128 | +async function processDirectory(pathToDir) { |
| 129 | + for (const inputFile of await fs.readdir(pathToDir, {withFileTypes: true})) { |
| 130 | + if (inputFile.isDirectory()) { |
| 131 | + await processDirectory(path.join(pathToDir, inputFile.name)); |
| 132 | + continue; |
93 | 133 | } |
94 | 134 |
|
95 | | - const outputName = `${path.basename(inputFile.name, ext)}.html`; |
96 | | - const pathToOutput = path.join(pathToOutputDir, outputName); |
| 135 | + const ext = path.extname(inputFile.name); |
97 | 136 |
|
98 | | - console.log('write', pathToOutput); |
99 | | - await fs.writeFile(pathToOutput, String(vFile), 'utf8'); |
| 137 | + if (processable.has(ext) && !isTemplate(inputFile.name)) { |
| 138 | + await processFile(pathToDir, inputFile); |
| 139 | + } else { |
| 140 | + await copyFile(pathToDir, inputFile); |
| 141 | + } |
100 | 142 | } |
101 | 143 | } |
102 | 144 |
|
|
0 commit comments