Solving the Problem of Garbled Characters in PDF Rendering
This commit is contained in:
@@ -259,6 +259,10 @@ class HTMLRenderer:
|
|||||||
jspdf_tag = f"<script>{jspdf}</script>" if jspdf else '<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>'
|
jspdf_tag = f"<script>{jspdf}</script>" if jspdf else '<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>'
|
||||||
mathjax_tag = f"<script defer>{mathjax}</script>" if mathjax else '<script defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>'
|
mathjax_tag = f"<script defer>{mathjax}</script>" if mathjax else '<script defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>'
|
||||||
|
|
||||||
|
# 加载PDF字体数据
|
||||||
|
pdf_font_data = self._load_pdf_font_data()
|
||||||
|
pdf_font_script = f"<script>window.pdfFontData = '{pdf_font_data}';</script>" if pdf_font_data else ""
|
||||||
|
|
||||||
return f"""
|
return f"""
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@@ -282,6 +286,7 @@ class HTMLRenderer:
|
|||||||
}};
|
}};
|
||||||
</script>
|
</script>
|
||||||
{mathjax_tag}
|
{mathjax_tag}
|
||||||
|
{pdf_font_script}
|
||||||
<style>
|
<style>
|
||||||
{css}
|
{css}
|
||||||
</style>
|
</style>
|
||||||
@@ -2353,6 +2358,7 @@ pre.code-block {{
|
|||||||
main {{
|
main {{
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
max-width: 100%;
|
||||||
}}
|
}}
|
||||||
.chapter > *,
|
.chapter > *,
|
||||||
.hero-section,
|
.hero-section,
|
||||||
@@ -2364,6 +2370,7 @@ figure,
|
|||||||
blockquote {{
|
blockquote {{
|
||||||
break-inside: avoid;
|
break-inside: avoid;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
|
max-width: 100%;
|
||||||
}}
|
}}
|
||||||
.chapter h2,
|
.chapter h2,
|
||||||
.chapter h3,
|
.chapter h3,
|
||||||
@@ -2375,18 +2382,37 @@ blockquote {{
|
|||||||
.chart-card,
|
.chart-card,
|
||||||
.table-wrap {{
|
.table-wrap {{
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
box-sizing: border-box;
|
||||||
}}
|
}}
|
||||||
.chart-card canvas {{
|
.chart-card canvas {{
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}}
|
||||||
|
.table-wrap {{
|
||||||
|
overflow-x: auto;
|
||||||
|
max-width: 100%;
|
||||||
}}
|
}}
|
||||||
.table-wrap table {{
|
.table-wrap table {{
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
}}
|
}}
|
||||||
.table-wrap table th,
|
.table-wrap table th,
|
||||||
.table-wrap table td {{
|
.table-wrap table td {{
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}}
|
||||||
|
/* 防止图片和图表溢出 */
|
||||||
|
img, canvas, svg {{
|
||||||
|
max-width: 100% !important;
|
||||||
|
height: auto !important;
|
||||||
|
}}
|
||||||
|
/* 确保所有容器不超出页面宽度 */
|
||||||
|
* {{
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 100%;
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
@@ -2858,6 +2884,9 @@ function exportPdf() {
|
|||||||
pdf.addFileToVFS('SourceHanSerifSC-Medium.otf', window.pdfFontData);
|
pdf.addFileToVFS('SourceHanSerifSC-Medium.otf', window.pdfFontData);
|
||||||
pdf.addFont('SourceHanSerifSC-Medium.otf', 'SourceHanSerif', 'normal');
|
pdf.addFont('SourceHanSerifSC-Medium.otf', 'SourceHanSerif', 'normal');
|
||||||
pdf.setFont('SourceHanSerif');
|
pdf.setFont('SourceHanSerif');
|
||||||
|
console.log('PDF字体已成功加载');
|
||||||
|
} else {
|
||||||
|
console.warn('PDF字体数据未找到,将使用默认字体');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Custom PDF font setup failed, fallback to default', err);
|
console.warn('Custom PDF font setup failed, fallback to default', err);
|
||||||
@@ -2890,11 +2919,13 @@ function exportPdf() {
|
|||||||
autoPaging: 'text',
|
autoPaging: 'text',
|
||||||
windowWidth: pxWidth,
|
windowWidth: pxWidth,
|
||||||
html2canvas: {
|
html2canvas: {
|
||||||
scale: Math.min(1.2, Math.max(0.8, pageWidth / (target.clientWidth || pageWidth))),
|
scale: Math.min(1.5, Math.max(1.0, pageWidth / (target.clientWidth || pageWidth))),
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
scrollX: 0,
|
scrollX: 0,
|
||||||
scrollY: -window.scrollY,
|
scrollY: -window.scrollY,
|
||||||
logging: false
|
logging: false,
|
||||||
|
allowTaint: true,
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
},
|
},
|
||||||
pagebreak: {
|
pagebreak: {
|
||||||
mode: ['css', 'legacy'],
|
mode: ['css', 'legacy'],
|
||||||
|
|||||||
+20
-2
@@ -3867,6 +3867,22 @@
|
|||||||
throw new Error('PDF依赖未加载');
|
throw new Error('PDF依赖未加载');
|
||||||
}
|
}
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||||
|
|
||||||
|
// 添加中文字体支持
|
||||||
|
try {
|
||||||
|
const fontData = iframe.contentWindow.pdfFontData || window.pdfFontData;
|
||||||
|
if (fontData) {
|
||||||
|
pdf.addFileToVFS('SourceHanSerifSC-Medium.otf', fontData);
|
||||||
|
pdf.addFont('SourceHanSerifSC-Medium.otf', 'SourceHanSerif', 'normal');
|
||||||
|
pdf.setFont('SourceHanSerif');
|
||||||
|
console.log('PDF字体已加载:SourceHanSerif');
|
||||||
|
} else {
|
||||||
|
console.warn('PDF字体数据未找到,将使用默认字体');
|
||||||
|
}
|
||||||
|
} catch (fontErr) {
|
||||||
|
console.warn('PDF字体加载失败:', fontErr);
|
||||||
|
}
|
||||||
|
|
||||||
const pageWidth = pdf.internal.pageSize.getWidth();
|
const pageWidth = pdf.internal.pageSize.getWidth();
|
||||||
const pxWidth = Math.max(target.scrollWidth || 0, Math.round(pageWidth * 3.78));
|
const pxWidth = Math.max(target.scrollWidth || 0, Math.round(pageWidth * 3.78));
|
||||||
const renderTask = pdf.html(target, {
|
const renderTask = pdf.html(target, {
|
||||||
@@ -3877,11 +3893,13 @@
|
|||||||
margin: [10, 10, 16, 10],
|
margin: [10, 10, 16, 10],
|
||||||
autoPaging: 'text',
|
autoPaging: 'text',
|
||||||
html2canvas: {
|
html2canvas: {
|
||||||
scale: Math.min(1.2, Math.max(0.8, pageWidth / (target.clientWidth || pageWidth))),
|
scale: Math.min(1.5, Math.max(1.0, pageWidth / (target.clientWidth || pageWidth))),
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
scrollX: 0,
|
scrollX: 0,
|
||||||
scrollY: -iframe.contentWindow.scrollY,
|
scrollY: -iframe.contentWindow.scrollY,
|
||||||
logging: false
|
logging: false,
|
||||||
|
allowTaint: true,
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
},
|
},
|
||||||
pagebreak: {
|
pagebreak: {
|
||||||
mode: ['css', 'legacy'],
|
mode: ['css', 'legacy'],
|
||||||
|
|||||||
Reference in New Issue
Block a user