const fs = require('fs');
const path = require('path');
const axios = require('axios');
const { minify } = require('html-minifier-terser');
async function inlineAsset(html, params) {
let asset;
const filePath = params.path.startsWith('http') ? params.path : path.join(params.sourceFolder, params.path);
if (fs.existsSync(filePath)) {
if (!params.inlineLocalAssets) {
if (filePath.includes('assets')) {
const assetPath = path.join(filePath.split('assets')[1]);
const targetPath = path.join(params.targetFolder, assetPath);
const targetFolder = path.dirname(targetPath);
const htmlAssetPath = `.${assetPath.replace(/\\/g, '/')}`;
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder, { recursive: true });
}
fs.copyFileSync(filePath, targetPath);
if (params.originalTag.toLowerCase() === 'link') {
html = html.replace(params.regex, ``);
} else if (params.originalTag.toLowerCase() === 'script') {
html = html.replace(params.regex, ``);
}
}
return html;
}
asset = fs.readFileSync(filePath, 'utf8');
} else {
if (!params.inlineRemoteAssets) {
return html;
}
asset = (await axios.get(filePath)).data;
}
return html.replace(params.regex, `<${params.tag}>\n${asset}\n${params.tag}>`);
}
function cleanTargetPath(targetDir) {
if (!fs.existsSync(targetDir)) {
return;
}
fs.readdirSync(targetDir).forEach((file) => {
const entryPath = path.join(targetDir, file);
const stat = fs.lstatSync(entryPath);
if (stat.isFile()) {
fs.unlinkSync(entryPath);
} else if (stat.isDirectory()) {
cleanTargetPath(entryPath);
}
});
fs.rmdirSync(targetDir);
}
async function inlineAssets(params) {
const sourceFolder = params.sourceFolder;
const targetFolder = params.targetFolder;
console.log(`Inlining assets from ${sourceFolder} to ${targetFolder}`);
const inputFile = path.join(sourceFolder, params.inputFile);
const outputFile = path.join(targetFolder, 'index.html');
let html = fs.readFileSync(inputFile, 'utf8');
const inlineLocalAssets = params.inlineLocalAssets || false;
const inlineRemoteAssets = params.inlineRemoteAssets || false;
cleanTargetPath(targetFolder);
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder, { recursive: true });
}
// Match and inline CSS links
const cssLinks = [...html.matchAll(/]*?\s+href=["'](.*?)["'][^>]*?>/gs)];
for (const match of cssLinks) {
html = await inlineAsset(html, {
path: match[1],
regex: match[0],
originalTag: 'link',
tag: 'style',
sourceFolder,
targetFolder,
inlineLocalAssets,
inlineRemoteAssets,
});
}
// Match and inline JavaScript src
const scriptLinks = [...html.matchAll(/