Skip to content

Commit 15cf9f1

Browse files
committed
refactor js templates
Signed-off-by: Andrei Gherghescu <[email protected]>
1 parent 920066c commit 15cf9f1

File tree

3 files changed

+70
-70
lines changed

3 files changed

+70
-70
lines changed

plotly_static/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ exclude = ["target/*"]
1616
webdriver_download = []
1717
geckodriver = []
1818
chromedriver = []
19+
html2pdf_export_timeout = []
1920

2021
[dependencies]
2122
log = "0.4"

plotly_static/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ use serde_json::map::Map as JsonMap;
274274
use urlencoding::encode;
275275
use webdriver::WebDriver;
276276

277-
use crate::template::{IMAGE_EXPORT_JS_SCRIPT, PDF_EXPORT_JS_SCRIPT};
277+
use crate::template::{image_export_js_script, pdf_export_js_script};
278278

279279
#[cfg(all(feature = "chromedriver", not(target_os = "windows")))]
280280
fn chrome_default_caps() -> Vec<&'static str> {
@@ -969,7 +969,7 @@ impl StaticExporter {
969969
plot.scale.into(),
970970
];
971971

972-
(PDF_EXPORT_JS_SCRIPT, args)
972+
(pdf_export_js_script(), args)
973973
}
974974
_ => {
975975
let args = vec![
@@ -980,11 +980,11 @@ impl StaticExporter {
980980
plot.scale.into(),
981981
];
982982

983-
(IMAGE_EXPORT_JS_SCRIPT, args)
983+
(image_export_js_script(), args)
984984
}
985985
};
986986

987-
let data = client.execute_async(js_script, args).await?;
987+
let data = client.execute_async(&js_script, args).await?;
988988

989989
// Don't close the client - keep it for reuse
990990
// client.close().await?;
@@ -1298,7 +1298,7 @@ mod tests {
12981298
assert!(dst.exists());
12991299
let metadata = std::fs::metadata(&dst).expect("Could not retrieve file metadata");
13001300
let file_size = metadata.len();
1301-
assert!(file_size > 0,);
1301+
assert!(file_size > 600000,);
13021302
// assert!(std::fs::remove_file(dst.as_path()).is_ok());
13031303
}
13041304

plotly_static/src/template.rs

Lines changed: 64 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use rand::{
1212
rng,
1313
};
1414

15-
pub(crate) const IMAGE_EXPORT_JS_SCRIPT: &str = r#"
15+
pub(crate) fn image_export_js_script() -> String {
16+
r#"
1617
const plot = arguments[0];
1718
const format = arguments[1];
1819
const width = arguments[2];
@@ -33,9 +34,19 @@ pub(crate) const IMAGE_EXPORT_JS_SCRIPT: &str = r#"
3334
console.error('Plotly error:', err);
3435
callback('ERROR:' + err.toString());
3536
});
36-
"#;
37+
"#
38+
.to_string()
39+
}
40+
41+
pub(crate) fn pdf_export_js_script() -> String {
42+
let timeout_ms = if cfg!(feature = "html2pdf_export_timeout") {
43+
500
44+
} else {
45+
250
46+
};
3747

38-
pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
48+
format!(
49+
r##"
3950
const plot = arguments[0];
4051
const format = arguments[1];
4152
const width = arguments[2];
@@ -50,45 +61,42 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
5061
const graph_div = document.getElementById('plotly-html-element');
5162
5263
// Check if html2pdf is available
53-
if (typeof html2pdf === 'undefined') {
64+
if (typeof html2pdf === 'undefined') {{
5465
console.error('html2pdf library not available');
5566
callback('ERROR:html2pdf library not loaded');
5667
return;
57-
}
58-
59-
console.log('html2pdf library is available');
68+
}}
6069
61-
let tempDiv = null;
62-
let mmWidth, mmHeight;
70+
let tempDiv = null;
6371
64-
Plotly.newPlot(graph_div, plot).then(function() {
65-
console.log('Plotly plot created successfully');
72+
const cleanup = () => {{
73+
if (tempDiv) {{
74+
document.body.removeChild(tempDiv);
75+
}}
76+
}};
6677
67-
// Force PNG format for PDF export to test if SVG is the issue
68-
return Plotly.toImage(graph_div, {
69-
format: 'png',
78+
Plotly.newPlot(graph_div, plot).then(function() {{
79+
return Plotly.toImage(graph_div, {{
80+
format: format,
7081
width: width,
7182
height: height,
72-
});
73-
}).then(function(dataUrl) {
83+
}});
84+
}}).then(function(dataUrl) {{
7485
console.log('Plotly image generated successfully');
7586
console.log('SVG data URL length:', dataUrl.length);
7687
console.log('SVG data URL preview:', dataUrl.substring(0, 200) + '...');
77-
78-
// Convert px to mm: 1px = 0.264583 mm
79-
mmWidth = width * 0.264583;
80-
mmHeight = height * 0.264583;
81-
82-
console.log('PDF dimensions (mm):', mmWidth, 'x', mmHeight);
88+
console.log('PDF dimensions (px):', width, 'x', height);
8389
8490
// Create a temporary div for the image
8591
tempDiv = document.createElement('div');
8692
tempDiv.style.width = width + 'px';
8793
tempDiv.style.height = height + 'px';
8894
tempDiv.style.background = 'white';
8995
tempDiv.style.position = 'fixed';
90-
tempDiv.style.left = '0px';
9196
tempDiv.style.top = '0px';
97+
tempDiv.style.left = '0px';
98+
tempDiv.style.margin = '0px';
99+
tempDiv.style.padding = '0px';
92100
tempDiv.style.overflow = 'hidden';
93101
tempDiv.style.boxSizing = 'border-box';
94102
tempDiv.style.zIndex = '9999';
@@ -105,35 +113,30 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
105113
img.style.objectFit = 'contain';
106114
img.style.maxWidth = '100%';
107115
img.style.maxHeight = '100%';
116+
img.style.verticalAlign = 'top';
117+
img.style.boxSizing = 'border-box';
108118
tempDiv.appendChild(img);
109119
110120
// Wait for the image to load
111-
return new Promise(function(resolve) {
112-
img.onload = function() {
121+
return new Promise(function(resolve) {{
122+
img.onload = function() {{
113123
console.log('SVG image loaded successfully');
114124
// Additional delay to ensure image is fully rendered
115-
setTimeout(function() {
116-
console.log('SVG rendering delay completed');
117-
resolve();
118-
}, 500);
119-
};
120-
img.onerror = function() {
121-
console.error('Failed to load SVG image');
122-
if (tempDiv) {
123-
document.body.removeChild(tempDiv);
124-
}
125+
// Brief delay to ensure image is fully rendered
126+
setTimeout(resolve, {timeout_ms});
127+
}};
128+
img.onerror = function() {{
129+
cleanup();
125130
callback('ERROR:Failed to load SVG image');
126-
};
127-
});
128-
}).then(function() {
131+
}};
132+
}});
133+
}}).then(function() {{
129134
console.log('Starting PDF generation...');
130-
131-
// Generate PDF with more robust configuration
132-
return html2pdf().from(tempDiv).set({
135+
return html2pdf().from(tempDiv).set({{
133136
margin: 0,
134137
filename: 'plotly-plot.pdf',
135-
image: { type: 'jpeg', quality: 1},
136-
html2canvas: {
138+
image: {{ type: 'jpeg', quality: 1}},
139+
html2canvas: {{
137140
scale: scale,
138141
backgroundColor: '#fff',
139142
useCORS: true,
@@ -143,31 +146,27 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
143146
height: height,
144147
imageTimeout: 15000,
145148
removeContainer: true,
146-
foreignObjectRendering: true
147-
},
148-
jsPDF: {
149-
unit: 'mm',
150-
format: [mmWidth, mmHeight],
151-
orientation: mmWidth > mmHeight ? 'landscape' : 'portrait',
149+
foreignObjectRendering: true,
150+
scrollY: 0,
151+
scrollX: 0
152+
}},
153+
jsPDF: {{
154+
unit: 'px',
155+
format: [width, height],
156+
orientation: width > height ? 'landscape' : 'portrait',
152157
compress: true
153-
}
154-
}).toPdf().output('datauristring');
155-
}).then(function(dataUri) {
156-
console.log('PDF generation completed successfully');
157-
// Clean up
158-
if (tempDiv) {
159-
document.body.removeChild(tempDiv);
160-
}
158+
}}
159+
}}).toPdf().output('datauristring');
160+
}}).then(function(dataUri) {{
161+
cleanup();
161162
callback(dataUri);
162-
}).catch(function(err) {
163-
console.error('PDF generation error:', err);
164-
// Clean up if tempDiv exists
165-
if (tempDiv) {
166-
document.body.removeChild(tempDiv);
167-
}
163+
}}).catch(function(err) {{
164+
cleanup();
168165
callback('ERROR:' + err.toString());
169-
});
170-
"##;
166+
}});
167+
"##
168+
)
169+
}
171170

172171
pub(crate) fn get_html_body(offline: bool) -> String {
173172
let offline_js = offline_js_sources();

0 commit comments

Comments
 (0)