mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
refac: chat pdf rendering
This commit is contained in:
parent
9657474a8d
commit
9143716463
@ -68,65 +68,66 @@
|
||||
if (containerElement) {
|
||||
try {
|
||||
const isDarkMode = document.documentElement.classList.contains('dark');
|
||||
const virtualWidth = 800; // Fixed width in px
|
||||
const pagePixelHeight = 1200; // Each slice height (adjust to avoid canvas bugs; generally 2–4k is safe)
|
||||
|
||||
console.log('isDarkMode', isDarkMode);
|
||||
|
||||
// Define a fixed virtual screen size
|
||||
const virtualWidth = 800; // Fixed width (adjust as needed)
|
||||
// Clone the container to avoid layout shifts
|
||||
// Clone & style once
|
||||
const clonedElement = containerElement.cloneNode(true);
|
||||
clonedElement.classList.add('text-black');
|
||||
clonedElement.classList.add('dark:text-white');
|
||||
clonedElement.style.width = `${virtualWidth}px`; // Apply fixed width
|
||||
clonedElement.style.height = 'auto'; // Allow content to expand
|
||||
clonedElement.style.width = `${virtualWidth}px`;
|
||||
clonedElement.style.position = 'absolute';
|
||||
clonedElement.style.left = '-9999px'; // Offscreen
|
||||
clonedElement.style.height = 'auto';
|
||||
document.body.appendChild(clonedElement);
|
||||
|
||||
document.body.appendChild(clonedElement); // Temporarily add to DOM
|
||||
// Get total height after attached to DOM
|
||||
const totalHeight = clonedElement.scrollHeight;
|
||||
let offsetY = 0;
|
||||
let page = 0;
|
||||
|
||||
// Render to canvas with predefined width
|
||||
// Prepare PDF
|
||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||
const imgWidth = 210; // A4 mm
|
||||
const pageHeight = 297; // A4 mm
|
||||
|
||||
while (offsetY < totalHeight) {
|
||||
// For each slice, adjust scrollTop to show desired part
|
||||
clonedElement.scrollTop = offsetY;
|
||||
|
||||
// Optionally: mask/hide overflowing content via CSS if needed
|
||||
clonedElement.style.maxHeight = `${pagePixelHeight}px`;
|
||||
// Only render the visible part
|
||||
const canvas = await html2canvas(clonedElement, {
|
||||
backgroundColor: isDarkMode ? '#000' : '#fff',
|
||||
useCORS: true,
|
||||
scale: 2, // Keep at 1x to avoid unexpected enlargements
|
||||
width: virtualWidth, // Set fixed virtual screen width
|
||||
windowWidth: virtualWidth // Ensure consistent rendering
|
||||
scale: 2,
|
||||
width: virtualWidth,
|
||||
height: Math.min(pagePixelHeight, totalHeight - offsetY),
|
||||
// Optionally: y offset for correct region?
|
||||
windowWidth: virtualWidth
|
||||
//windowHeight: pagePixelHeight,
|
||||
});
|
||||
|
||||
document.body.removeChild(clonedElement); // Clean up temp element
|
||||
|
||||
const imgData = canvas.toDataURL('image/png');
|
||||
|
||||
// A4 page settings
|
||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||
const imgWidth = 210; // A4 width in mm
|
||||
const pageHeight = 297; // A4 height in mm
|
||||
|
||||
// Maintain aspect ratio
|
||||
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
||||
let heightLeft = imgHeight;
|
||||
let position = 0;
|
||||
const position = 0; // Always first line, since we've clipped vertically
|
||||
|
||||
if (page > 0) pdf.addPage();
|
||||
|
||||
// Set page background for dark mode
|
||||
if (isDarkMode) {
|
||||
pdf.setFillColor(0, 0, 0);
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F'); // Apply black bg
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F'); // black bg
|
||||
}
|
||||
|
||||
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
||||
heightLeft -= pageHeight;
|
||||
|
||||
// Handle additional pages
|
||||
while (heightLeft > 0) {
|
||||
position -= pageHeight;
|
||||
pdf.addPage();
|
||||
|
||||
if (isDarkMode) {
|
||||
pdf.setFillColor(0, 0, 0);
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F');
|
||||
offsetY += pagePixelHeight;
|
||||
page++;
|
||||
}
|
||||
|
||||
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
||||
heightLeft -= pageHeight;
|
||||
}
|
||||
document.body.removeChild(clonedElement);
|
||||
|
||||
pdf.save(`chat-${chat.chat.title}.pdf`);
|
||||
} catch (error) {
|
||||
|
@ -85,65 +85,67 @@
|
||||
|
||||
if (containerElement) {
|
||||
try {
|
||||
const isDarkMode = $theme.includes('dark'); // Check theme mode
|
||||
const isDarkMode = document.documentElement.classList.contains('dark');
|
||||
const virtualWidth = 800; // Fixed width in px
|
||||
const pagePixelHeight = 1200; // Each slice height (adjust to avoid canvas bugs; generally 2–4k is safe)
|
||||
|
||||
// Define a fixed virtual screen size
|
||||
const virtualWidth = 1024; // Fixed width (adjust as needed)
|
||||
const virtualHeight = 1400; // Fixed height (adjust as needed)
|
||||
|
||||
// Clone the container to avoid layout shifts
|
||||
// Clone & style once
|
||||
const clonedElement = containerElement.cloneNode(true);
|
||||
clonedElement.style.width = `${virtualWidth}px`; // Apply fixed width
|
||||
clonedElement.style.height = 'auto'; // Allow content to expand
|
||||
clonedElement.classList.add('text-black');
|
||||
clonedElement.classList.add('dark:text-white');
|
||||
clonedElement.style.width = `${virtualWidth}px`;
|
||||
clonedElement.style.position = 'absolute';
|
||||
clonedElement.style.left = '-9999px'; // Offscreen
|
||||
clonedElement.style.height = 'auto';
|
||||
document.body.appendChild(clonedElement);
|
||||
|
||||
document.body.appendChild(clonedElement); // Temporarily add to DOM
|
||||
// Get total height after attached to DOM
|
||||
const totalHeight = clonedElement.scrollHeight;
|
||||
let offsetY = 0;
|
||||
let page = 0;
|
||||
|
||||
// Render to canvas with predefined width
|
||||
// Prepare PDF
|
||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||
const imgWidth = 210; // A4 mm
|
||||
const pageHeight = 297; // A4 mm
|
||||
|
||||
while (offsetY < totalHeight) {
|
||||
// For each slice, adjust scrollTop to show desired part
|
||||
clonedElement.scrollTop = offsetY;
|
||||
|
||||
// Optionally: mask/hide overflowing content via CSS if needed
|
||||
clonedElement.style.maxHeight = `${pagePixelHeight}px`;
|
||||
// Only render the visible part
|
||||
const canvas = await html2canvas(clonedElement, {
|
||||
backgroundColor: isDarkMode ? '#000' : '#fff',
|
||||
useCORS: true,
|
||||
scale: 2, // Keep at 1x to avoid unexpected enlargements
|
||||
width: virtualWidth, // Set fixed virtual screen width
|
||||
windowWidth: virtualWidth, // Ensure consistent rendering
|
||||
windowHeight: virtualHeight
|
||||
scale: 2,
|
||||
width: virtualWidth,
|
||||
height: Math.min(pagePixelHeight, totalHeight - offsetY),
|
||||
// Optionally: y offset for correct region?
|
||||
windowWidth: virtualWidth
|
||||
//windowHeight: pagePixelHeight,
|
||||
});
|
||||
|
||||
document.body.removeChild(clonedElement); // Clean up temp element
|
||||
|
||||
const imgData = canvas.toDataURL('image/png');
|
||||
|
||||
// A4 page settings
|
||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||
const imgWidth = 210; // A4 width in mm
|
||||
const pageHeight = 297; // A4 height in mm
|
||||
|
||||
// Maintain aspect ratio
|
||||
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
||||
let heightLeft = imgHeight;
|
||||
let position = 0;
|
||||
const position = 0; // Always first line, since we've clipped vertically
|
||||
|
||||
if (page > 0) pdf.addPage();
|
||||
|
||||
// Set page background for dark mode
|
||||
if (isDarkMode) {
|
||||
pdf.setFillColor(0, 0, 0);
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F'); // Apply black bg
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F'); // black bg
|
||||
}
|
||||
|
||||
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
||||
heightLeft -= pageHeight;
|
||||
|
||||
// Handle additional pages
|
||||
while (heightLeft > 0) {
|
||||
position -= pageHeight;
|
||||
pdf.addPage();
|
||||
|
||||
if (isDarkMode) {
|
||||
pdf.setFillColor(0, 0, 0);
|
||||
pdf.rect(0, 0, imgWidth, pageHeight, 'F');
|
||||
offsetY += pagePixelHeight;
|
||||
page++;
|
||||
}
|
||||
|
||||
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
||||
heightLeft -= pageHeight;
|
||||
}
|
||||
document.body.removeChild(clonedElement);
|
||||
|
||||
pdf.save(`chat-${chat.chat.title}.pdf`);
|
||||
} catch (error) {
|
||||
|
Loading…
Reference in New Issue
Block a user