diff --git a/src/generators/legacy-html/index.mjs b/src/generators/legacy-html/index.mjs
index f8c1e58f..c100967b 100644
--- a/src/generators/legacy-html/index.mjs
+++ b/src/generators/legacy-html/index.mjs
@@ -1,12 +1,13 @@
'use strict';
-import { cp, readFile, rm, writeFile } from 'node:fs/promises';
+import { readFile, rm, writeFile, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import HTMLMinifier from '@minify-html/node';
import buildContent from './utils/buildContent.mjs';
import dropdowns from './utils/buildDropdowns.mjs';
+import { safeCopy } from './utils/safeCopy.mjs';
import tableOfContents from './utils/tableOfContents.mjs';
import { groupNodesByModule } from '../../utils/generators.mjs';
import { getRemarkRehype } from '../../utils/remark.mjs';
@@ -169,6 +170,9 @@ export default {
}
if (output) {
+ // Define the source folder for API docs assets
+ const srcAssets = join(baseDir, 'assets');
+
// Define the output folder for API docs assets
const assetsFolder = join(output, 'assets');
@@ -177,13 +181,11 @@ export default {
// If the path does not exists, it will simply ignore and continue
await rm(assetsFolder, { recursive: true, force: true, maxRetries: 10 });
- // We copy all the other assets to the output folder at the end of the process
- // to ensure that all latest changes on the styles are applied to the output
- // Note.: This is not meant to be used for DX/developer purposes.
- await cp(join(baseDir, 'assets'), assetsFolder, {
- recursive: true,
- force: true,
- });
+ // Creates the assets folder if it does not exist
+ await mkdir(assetsFolder, { recursive: true });
+
+ // Copy all files from assets folder to output, skipping unchanged files
+ await safeCopy(srcAssets, assetsFolder);
}
return generatedValues;
diff --git a/src/generators/legacy-html/utils/safeCopy.mjs b/src/generators/legacy-html/utils/safeCopy.mjs
new file mode 100644
index 00000000..e96b62ed
--- /dev/null
+++ b/src/generators/legacy-html/utils/safeCopy.mjs
@@ -0,0 +1,38 @@
+'use strict';
+
+import { readFile, writeFile, stat, readdir } from 'node:fs/promises';
+import { join } from 'node:path';
+
+/**
+ * Safely copies files from source to target directory, skipping files that haven't changed
+ * based on file stats (size and modification time)
+ *
+ * @param {string} srcDir - Source directory path
+ * @param {string} targetDir - Target directory path
+ */
+export async function safeCopy(srcDir, targetDir) {
+ const files = await readdir(srcDir);
+
+ for (const file of files) {
+ const sourcePath = join(srcDir, file);
+ const targetPath = join(targetDir, file);
+
+ const [sStat, tStat] = await Promise.allSettled([
+ stat(sourcePath),
+ stat(targetPath),
+ ]);
+
+ const shouldWrite =
+ tStat.status === 'rejected' ||
+ sStat.value.size !== tStat.value.size ||
+ sStat.value.mtimeMs > tStat.value.mtimeMs;
+
+ if (!shouldWrite) {
+ continue;
+ }
+
+ const fileContent = await readFile(sourcePath);
+
+ await writeFile(targetPath, fileContent);
+ }
+}