Skip to content

Commit 45e537a

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

File tree

3 files changed

+69
-70
lines changed

3 files changed

+69
-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::{pdf_export_js_script, image_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: 63 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,18 @@ pub(crate) const IMAGE_EXPORT_JS_SCRIPT: &str = r#"
3334
console.error('Plotly error:', err);
3435
callback('ERROR:' + err.toString());
3536
});
36-
"#;
37+
"#.to_string()
38+
}
39+
40+
pub(crate) fn pdf_export_js_script() -> String {
41+
let timeout_ms = if cfg!(feature = "html2pdf_export_timeout") {
42+
500
43+
} else {
44+
250
45+
};
3746

38-
pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
47+
format!(
48+
r##"
3949
const plot = arguments[0];
4050
const format = arguments[1];
4151
const width = arguments[2];
@@ -50,45 +60,42 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
5060
const graph_div = document.getElementById('plotly-html-element');
5161
5262
// Check if html2pdf is available
53-
if (typeof html2pdf === 'undefined') {
63+
if (typeof html2pdf === 'undefined') {{
5464
console.error('html2pdf library not available');
5565
callback('ERROR:html2pdf library not loaded');
5666
return;
57-
}
58-
59-
console.log('html2pdf library is available');
67+
}}
6068
61-
let tempDiv = null;
62-
let mmWidth, mmHeight;
69+
let tempDiv = null;
6370
64-
Plotly.newPlot(graph_div, plot).then(function() {
65-
console.log('Plotly plot created successfully');
71+
const cleanup = () => {{
72+
if (tempDiv) {{
73+
document.body.removeChild(tempDiv);
74+
}}
75+
}};
6676
67-
// Force PNG format for PDF export to test if SVG is the issue
68-
return Plotly.toImage(graph_div, {
69-
format: 'png',
77+
Plotly.newPlot(graph_div, plot).then(function() {{
78+
return Plotly.toImage(graph_div, {{
79+
format: format,
7080
width: width,
7181
height: height,
72-
});
73-
}).then(function(dataUrl) {
82+
}});
83+
}}).then(function(dataUrl) {{
7484
console.log('Plotly image generated successfully');
7585
console.log('SVG data URL length:', dataUrl.length);
7686
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);
87+
console.log('PDF dimensions (px):', width, 'x', height);
8388
8489
// Create a temporary div for the image
8590
tempDiv = document.createElement('div');
8691
tempDiv.style.width = width + 'px';
8792
tempDiv.style.height = height + 'px';
8893
tempDiv.style.background = 'white';
8994
tempDiv.style.position = 'fixed';
90-
tempDiv.style.left = '0px';
9195
tempDiv.style.top = '0px';
96+
tempDiv.style.left = '0px';
97+
tempDiv.style.margin = '0px';
98+
tempDiv.style.padding = '0px';
9299
tempDiv.style.overflow = 'hidden';
93100
tempDiv.style.boxSizing = 'border-box';
94101
tempDiv.style.zIndex = '9999';
@@ -105,35 +112,30 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
105112
img.style.objectFit = 'contain';
106113
img.style.maxWidth = '100%';
107114
img.style.maxHeight = '100%';
115+
img.style.verticalAlign = 'top';
116+
img.style.boxSizing = 'border-box';
108117
tempDiv.appendChild(img);
109118
110119
// Wait for the image to load
111-
return new Promise(function(resolve) {
112-
img.onload = function() {
120+
return new Promise(function(resolve) {{
121+
img.onload = function() {{
113122
console.log('SVG image loaded successfully');
114123
// 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-
}
124+
// Brief delay to ensure image is fully rendered
125+
setTimeout(resolve, {timeout_ms});
126+
}};
127+
img.onerror = function() {{
128+
cleanup();
125129
callback('ERROR:Failed to load SVG image');
126-
};
127-
});
128-
}).then(function() {
130+
}};
131+
}});
132+
}}).then(function() {{
129133
console.log('Starting PDF generation...');
130-
131-
// Generate PDF with more robust configuration
132-
return html2pdf().from(tempDiv).set({
134+
return html2pdf().from(tempDiv).set({{
133135
margin: 0,
134136
filename: 'plotly-plot.pdf',
135-
image: { type: 'jpeg', quality: 1},
136-
html2canvas: {
137+
image: {{ type: 'jpeg', quality: 1}},
138+
html2canvas: {{
137139
scale: scale,
138140
backgroundColor: '#fff',
139141
useCORS: true,
@@ -143,31 +145,27 @@ pub(crate) const PDF_EXPORT_JS_SCRIPT: &str = r##"
143145
height: height,
144146
imageTimeout: 15000,
145147
removeContainer: true,
146-
foreignObjectRendering: true
147-
},
148-
jsPDF: {
149-
unit: 'mm',
150-
format: [mmWidth, mmHeight],
151-
orientation: mmWidth > mmHeight ? 'landscape' : 'portrait',
148+
foreignObjectRendering: true,
149+
scrollY: 0,
150+
scrollX: 0
151+
}},
152+
jsPDF: {{
153+
unit: 'px',
154+
format: [width, height],
155+
orientation: width > height ? 'landscape' : 'portrait',
152156
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-
}
157+
}}
158+
}}).toPdf().output('datauristring');
159+
}}).then(function(dataUri) {{
160+
cleanup();
161161
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-
}
162+
}}).catch(function(err) {{
163+
cleanup();
168164
callback('ERROR:' + err.toString());
169-
});
170-
"##;
165+
}});
166+
"##
167+
)
168+
}
171169

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

0 commit comments

Comments
 (0)