HTML to PDF Converter - Complete Fix
HTML to PDF Converter
Convert web pages and HTML code to perfectly formatted PDF documents
PDF Options
Preview
Content preview will appear here
Processing...
Please wait...
`;// Initialize application
document.addEventListener('DOMContentLoaded', function() {
initializeApp();
});function initializeApp() {
// Initialize CodeMirror for HTML editing
const htmlTextarea = document.getElementById('htmlEditor');
htmlEditor = CodeMirror.fromTextArea(htmlTextarea, {
mode: 'htmlmixed',
theme: 'monokai',
lineNumbers: true,
lineWrapping: true,
autoCloseTags: true,
matchBrackets: true,
indentUnit: 2,
tabSize: 2
});// Set initial sample content
htmlEditor.setValue(sampleHtml);// Event listeners
document.getElementById('urlModeBtn').addEventListener('click', () => switchMode('url'));
document.getElementById('htmlModeBtn').addEventListener('click', () => switchMode('html'));
document.getElementById('loadUrlBtn').addEventListener('click', loadUrl);
document.getElementById('previewHtmlBtn').addEventListener('click', previewHtml);
document.getElementById('sampleHtmlBtn').addEventListener('click', loadSampleHtml);
document.getElementById('generatePdfBtn').addEventListener('click', generatePdf);
document.getElementById('refreshPreviewBtn').addEventListener('click', refreshPreview);// Auto-preview for HTML mode
htmlEditor.on('change', debounce(previewHtml, 1000));// Initialize with HTML mode and show preview
switchMode('html');
setTimeout(previewHtml, 100);
}function switchMode(mode) {
currentMode = mode;
// Update button states
document.getElementById('urlModeBtn').classList.toggle('bg-blue-500', mode === 'url');
document.getElementById('urlModeBtn').classList.toggle('text-white', mode === 'url');
document.getElementById('urlModeBtn').classList.toggle('text-gray-700', mode !== 'url');
document.getElementById('urlModeBtn').classList.toggle('hover:bg-gray-50', mode !== 'url');document.getElementById('htmlModeBtn').classList.toggle('bg-blue-500', mode === 'html');
document.getElementById('htmlModeBtn').classList.toggle('text-white', mode === 'html');
document.getElementById('htmlModeBtn').classList.toggle('text-gray-700', mode !== 'html');
document.getElementById('htmlModeBtn').classList.toggle('hover:bg-gray-50', mode !== 'html');// Show/hide appropriate sections
document.getElementById('urlMode').classList.toggle('hidden', mode !== 'url');
document.getElementById('htmlMode').classList.toggle('hidden', mode !== 'html');// Clear preview when switching modes
clearPreview();
}function showLoading(text = 'Processing...') {
document.getElementById('loadingText').textContent = text;
document.getElementById('loadingOverlay').classList.remove('hidden');
}function hideLoading() {
document.getElementById('loadingOverlay').classList.add('hidden');
}function showError(message) {
document.getElementById('errorText').textContent = message;
document.getElementById('errorMessage').classList.remove('hidden');
setTimeout(() => {
document.getElementById('errorMessage').classList.add('hidden');
}, 5000);
}function showSuccess(message) {
document.getElementById('successText').textContent = message;
document.getElementById('successMessage').classList.remove('hidden');
setTimeout(() => {
document.getElementById('successMessage').classList.add('hidden');
}, 3000);
}async function loadUrl() {
const url = document.getElementById('urlInput').value.trim();
if (!url) {
showError('Please enter a valid URL');
return;
}if (!isValidUrl(url)) {
showError('Please enter a valid URL format (e.g., https://example.com)');
return;
}showLoading('Loading webpage...');
document.getElementById('urlStatus').textContent = 'Loading...';try {
// Method 1: Try direct fetch (will fail for most external sites due to CORS)
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}const html = await response.text();
displayUrlPreview(html, url);
document.getElementById('urlStatus').textContent = 'Loaded successfully';
document.getElementById('urlStatus').className = 'text-sm text-green-600';} catch (error) {
// Method 2: Try using a CORS proxy
try {
const proxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`;
const proxyResponse = await fetch(proxyUrl);
if (!proxyResponse.ok) {
throw new Error('Proxy request failed');
}const html = await proxyResponse.text();
displayUrlPreview(html, url);
document.getElementById('urlStatus').textContent = 'Loaded via proxy';
document.getElementById('urlStatus').className = 'text-sm text-green-600';} catch (proxyError) {
// Method 3: Use iframe as fallback
displayUrlPreviewIframe(url);
document.getElementById('urlStatus').textContent = 'Loaded in iframe (limited conversion support)';
document.getElementById('urlStatus').className = 'text-sm text-yellow-600';
}
}hideLoading();
}function displayUrlPreview(html, baseUrl) {
const previewContainer = document.getElementById('previewContainer');
// Create iframe for preview
const iframe = document.createElement('iframe');
iframe.className = 'w-full h-96 border-0';
iframe.sandbox = 'allow-same-origin allow-scripts';
previewContainer.innerHTML = '';
previewContainer.appendChild(iframe);// Write HTML to iframe
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(html);
iframeDoc.close();// Store content for PDF generation
window.currentContent = html;
window.currentContentType = 'html';
}function displayUrlPreviewIframe(url) {
const previewContainer = document.getElementById('previewContainer');
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.className = 'w-full h-96 border-0';
iframe.sandbox = 'allow-same-origin allow-scripts';
previewContainer.innerHTML = '';
previewContainer.appendChild(iframe);// Store URL for PDF generation
window.currentContent = url;
window.currentContentType = 'url';
}function previewHtml() {
const html = htmlEditor.getValue();
if (!html.trim()) {
clearPreview();
return;
}const previewContainer = document.getElementById('previewContainer');
// Create iframe for preview
const iframe = document.createElement('iframe');
iframe.className = 'w-full h-96 border-0';
iframe.sandbox = 'allow-same-origin allow-scripts';
previewContainer.innerHTML = '';
previewContainer.appendChild(iframe);// Write HTML to iframe
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(html);
iframeDoc.close();// Store content for PDF generation
window.currentContent = html;
window.currentContentType = 'html';
}function loadSampleHtml() {
htmlEditor.setValue(sampleHtml);
setTimeout(previewHtml, 100);
}function clearPreview() {
document.getElementById('previewContainer').innerHTML = `
Content preview will appear here
`;
window.currentContent = null;
window.currentContentType = null;
}function refreshPreview() {
if (currentMode === 'html') {
previewHtml();
} else {
const url = document.getElementById('urlInput').value.trim();
if (url) {
loadUrl();
}
}
}async function generatePdf() {
if (!window.currentContent) {
showError('Please load content first');
return;
}showLoading('Generating PDF...');try {
const { jsPDF } = window.jspdf;
const pageSize = document.getElementById('pageSize').value;
const orientation = document.getElementById('orientation').value;
const printBackground = document.getElementById('printBackground').checked;// Create PDF document
const pdf = new jsPDF({
orientation: orientation,
unit: 'mm',
format: pageSize
});if (window.currentContentType === 'html') {
// Create a temporary container for rendering
const tempContainer = document.createElement('div');
tempContainer.innerHTML = window.currentContent;
tempContainer.style.width = '210mm'; // A4 width
tempContainer.style.position = 'absolute';
tempContainer.style.left = '-9999px';
tempContainer.style.background = 'white';
tempContainer.style.padding = '10mm';
document.body.appendChild(tempContainer);// Capture the content
const canvas = await html2canvas(tempContainer, {
scale: 2,
useCORS: true,
allowTaint: true,
backgroundColor: printBackground ? null : '#ffffff'
});// Calculate dimensions
const imgData = canvas.toDataURL('image/jpeg', 0.95);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = pdfWidth;
const imgHeight = (canvas.height * imgWidth) / canvas.width;// Add image to PDF
let heightLeft = imgHeight;
let position = 0;// Add first page
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
heightLeft -= pdfHeight;// Add additional pages if needed
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
heightLeft -= pdfHeight;
}// Clean up
document.body.removeChild(tempContainer);} else {
// For URL content, add a message
pdf.text('PDF generation from external URLs is limited due to browser security restrictions.', 20, 20);
pdf.text('Please use the HTML code mode for best results.', 20, 40);
}// Save PDF
const filename = `converted_${new Date().toISOString().slice(0, 10)}.pdf`;
pdf.save(filename);showSuccess('PDF generated successfully!');} catch (error) {
console.error('PDF generation error:', error);
showError('Failed to generate PDF. Please try again.');
}hideLoading();
}// Utility functions
function isValidUrl(string) {
try {
new URL(string);
return true;
} catch (_) {
return false;
}
}function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}