pvanand's picture
Upload 7 files
68ca1f1 verified
// minify.js
const { minify } = require('html-minifier');
const cheerio = require('cheerio');
function sanitizeHtml(html) {
try {
// Remove conditional comments
html = html.replace(/<!--\[if.*?<!\[endif\]-->/gs, '');
// Fix incomplete URLs
html = html.replace(/src="https?:\/\/[^"]*\.{3}"/g, '');
// Remove problematic script tags
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
return html;
} catch (err) {
console.warn('HTML sanitization failed:', err);
return html;
}
}
function validateHtml(html) {
try {
const $ = cheerio.load(html, {
xmlMode: false,
decodeEntities: false
});
const issues = [];
if ($('html').length === 0) issues.push('Missing html tag');
if ($('head').length === 0) issues.push('Missing head tag');
if ($('body').length === 0) issues.push('Missing body tag');
return issues;
} catch (err) {
console.warn('HTML validation failed:', err);
return ['Validation error: ' + err.message];
}
}
function safeMinify(html, options = {}) {
const defaultOptions = {
removeComments: true,
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
conservativeCollapse: true,
keepClosingSlash: true,
removeAttributeQuotes: false,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: false,
removeStyleLinkTypeAttributes: false,
sortAttributes: true,
sortClassName: true
};
const minifyOptions = { ...defaultOptions, ...options };
try {
// Try full minification first
return minify(html, minifyOptions);
} catch (err) {
console.warn('Full minification failed, trying conservative mode:', err);
try {
// Fall back to conservative minification
return minify(html, {
removeComments: true,
collapseWhitespace: true,
conservativeCollapse: true,
keepClosingSlash: true,
removeAttributeQuotes: false,
removeEmptyAttributes: false,
removeRedundantAttributes: false
});
} catch (err2) {
console.error('Conservative minification also failed:', err2);
return html;
}
}
}
function minifyHtml(html, options = {}) {
const result = {
originalSize: html.length,
minifiedHtml: '',
success: false,
issues: [],
stats: {},
error: null
};
try {
// Step 1: Validate HTML
const validationIssues = validateHtml(html);
result.issues = validationIssues;
// Step 2: Sanitize HTML
const sanitized = sanitizeHtml(html);
// Step 3: Minify HTML
const minified = safeMinify(sanitized, options);
result.minifiedHtml = minified;
result.success = true;
// Step 4: Calculate stats
result.stats = {
originalSize: html.length,
minifiedSize: minified.length,
reduction: ((html.length - minified.length) / html.length * 100).toFixed(2) + '%',
validationIssues: validationIssues.length,
timestamp: new Date().toISOString()
};
} catch (err) {
result.error = {
message: err.message,
stack: err.stack
};
result.minifiedHtml = html; // Return original HTML if processing fails
}
return result;
}
module.exports = {
minifyHtml,
validateHtml,
sanitizeHtml
};