Skip to content

Commit f3edbc7

Browse files
committed
correct inline plotly theme merge
1 parent 9715cf9 commit f3edbc7

2 files changed

Lines changed: 158 additions & 0 deletions

File tree

pywry/pywry/frontend/src/plotly-widget.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,84 @@
11
/*PyWry Plotly Widget*/
22

3+
if (!window.__pywryDeepMerge) {
4+
window.__pywryDeepMerge = function deepMerge(base, overrides) {
5+
if (!overrides || typeof overrides !== 'object') return base ? JSON.parse(JSON.stringify(base)) : {};
6+
if (!base || typeof base !== 'object') return JSON.parse(JSON.stringify(overrides));
7+
var result = JSON.parse(JSON.stringify(base));
8+
var keys = Object.keys(overrides);
9+
for (var i = 0; i < keys.length; i++) {
10+
var key = keys[i];
11+
var val = overrides[key];
12+
if (val !== null && typeof val === 'object' && !Array.isArray(val)
13+
&& result[key] !== null && typeof result[key] === 'object' && !Array.isArray(result[key])) {
14+
result[key] = deepMerge(result[key], val);
15+
} else {
16+
result[key] = (val !== null && typeof val === 'object') ? JSON.parse(JSON.stringify(val)) : val;
17+
}
18+
}
19+
return result;
20+
};
21+
}
22+
23+
if (!window.__pywryMergeThemeTemplate) {
24+
window.__pywryMergeThemeTemplate = function(plotDiv, themeTemplateName, userTemplate, userTemplateDark, userTemplateLight) {
25+
var templates = window.PYWRY_PLOTLY_TEMPLATES || {};
26+
var baseTemplate = templates[themeTemplateName] || {};
27+
28+
if (userTemplateDark && typeof userTemplateDark === 'object' && Object.keys(userTemplateDark).length > 0) {
29+
plotDiv.__pywry_user_template_dark__ = JSON.parse(JSON.stringify(userTemplateDark));
30+
}
31+
if (userTemplateLight && typeof userTemplateLight === 'object' && Object.keys(userTemplateLight).length > 0) {
32+
plotDiv.__pywry_user_template_light__ = JSON.parse(JSON.stringify(userTemplateLight));
33+
}
34+
if (userTemplate && typeof userTemplate === 'object' && Object.keys(userTemplate).length > 0
35+
&& !userTemplateDark && !userTemplateLight) {
36+
plotDiv.__pywry_user_template__ = JSON.parse(JSON.stringify(userTemplate));
37+
}
38+
39+
var isDark = themeTemplateName.indexOf('dark') !== -1;
40+
var overrides = null;
41+
if (isDark && plotDiv.__pywry_user_template_dark__) {
42+
overrides = plotDiv.__pywry_user_template_dark__;
43+
} else if (!isDark && plotDiv.__pywry_user_template_light__) {
44+
overrides = plotDiv.__pywry_user_template_light__;
45+
} else {
46+
overrides = plotDiv.__pywry_user_template__;
47+
}
48+
49+
if (!overrides) return JSON.parse(JSON.stringify(baseTemplate));
50+
return window.__pywryDeepMerge(baseTemplate, overrides);
51+
};
52+
}
53+
54+
if (!window.__pywryStripThemeColors) {
55+
window.__pywryStripThemeColors = function(plotDiv) {
56+
var layout = plotDiv.layout;
57+
if (!layout) return;
58+
59+
delete layout.paper_bgcolor;
60+
delete layout.plot_bgcolor;
61+
delete layout.colorway;
62+
63+
if (layout.font) {
64+
delete layout.font.color;
65+
if (Object.keys(layout.font).length === 0) delete layout.font;
66+
}
67+
68+
var axisRe = /^[xyz]axis\d*$/;
69+
var keys = Object.keys(layout);
70+
for (var i = 0; i < keys.length; i++) {
71+
if (axisRe.test(keys[i]) && layout[keys[i]] && typeof layout[keys[i]] === 'object') {
72+
var ax = layout[keys[i]];
73+
delete ax.color;
74+
delete ax.gridcolor;
75+
delete ax.linecolor;
76+
delete ax.zerolinecolor;
77+
}
78+
}
79+
};
80+
}
81+
382
function render({ model, el }) {
483
el.innerHTML = '';
584

pywry/pywry/inline.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,6 +3105,85 @@ def generate_plotly_html(
31053105
# Use window.Plotly for anywidget compatibility (ESM scope)
31063106
plotly_handlers_script = f"""<script>
31073107
(function() {{
3108+
if (!window.__pywryDeepMerge) {{
3109+
window.__pywryDeepMerge = function deepMerge(base, overrides) {{
3110+
if (!overrides || typeof overrides !== 'object') return base ? JSON.parse(JSON.stringify(base)) : {{}};
3111+
if (!base || typeof base !== 'object') return JSON.parse(JSON.stringify(overrides));
3112+
var result = JSON.parse(JSON.stringify(base));
3113+
var keys = Object.keys(overrides);
3114+
for (var i = 0; i < keys.length; i++) {{
3115+
var key = keys[i];
3116+
var val = overrides[key];
3117+
if (val !== null && typeof val === 'object' && !Array.isArray(val)
3118+
&& result[key] !== null && typeof result[key] === 'object' && !Array.isArray(result[key])) {{
3119+
result[key] = deepMerge(result[key], val);
3120+
}} else {{
3121+
result[key] = (val !== null && typeof val === 'object') ? JSON.parse(JSON.stringify(val)) : val;
3122+
}}
3123+
}}
3124+
return result;
3125+
}};
3126+
}}
3127+
3128+
if (!window.__pywryMergeThemeTemplate) {{
3129+
window.__pywryMergeThemeTemplate = function(chartEl, themeTemplateName, userTemplate, userTemplateDark, userTemplateLight) {{
3130+
var templates = window.PYWRY_PLOTLY_TEMPLATES || {{}};
3131+
var baseTemplate = templates[themeTemplateName] || {{}};
3132+
3133+
if (userTemplateDark && typeof userTemplateDark === 'object' && Object.keys(userTemplateDark).length > 0) {{
3134+
chartEl.__pywry_user_template_dark__ = JSON.parse(JSON.stringify(userTemplateDark));
3135+
}}
3136+
if (userTemplateLight && typeof userTemplateLight === 'object' && Object.keys(userTemplateLight).length > 0) {{
3137+
chartEl.__pywry_user_template_light__ = JSON.parse(JSON.stringify(userTemplateLight));
3138+
}}
3139+
if (userTemplate && typeof userTemplate === 'object' && Object.keys(userTemplate).length > 0
3140+
&& !userTemplateDark && !userTemplateLight) {{
3141+
chartEl.__pywry_user_template__ = JSON.parse(JSON.stringify(userTemplate));
3142+
}}
3143+
3144+
var isDarkTemplate = themeTemplateName.indexOf('dark') !== -1;
3145+
var overrides = null;
3146+
if (isDarkTemplate && chartEl.__pywry_user_template_dark__) {{
3147+
overrides = chartEl.__pywry_user_template_dark__;
3148+
}} else if (!isDarkTemplate && chartEl.__pywry_user_template_light__) {{
3149+
overrides = chartEl.__pywry_user_template_light__;
3150+
}} else {{
3151+
overrides = chartEl.__pywry_user_template__;
3152+
}}
3153+
3154+
if (!overrides) return JSON.parse(JSON.stringify(baseTemplate));
3155+
return window.__pywryDeepMerge(baseTemplate, overrides);
3156+
}};
3157+
}}
3158+
3159+
if (!window.__pywryStripThemeColors) {{
3160+
window.__pywryStripThemeColors = function(chartEl) {{
3161+
var layout = chartEl.layout;
3162+
if (!layout) return;
3163+
3164+
delete layout.paper_bgcolor;
3165+
delete layout.plot_bgcolor;
3166+
delete layout.colorway;
3167+
3168+
if (layout.font) {{
3169+
delete layout.font.color;
3170+
if (Object.keys(layout.font).length === 0) delete layout.font;
3171+
}}
3172+
3173+
var axisRe = /^[xyz]axis\\d*$/;
3174+
var keys = Object.keys(layout);
3175+
for (var i = 0; i < keys.length; i++) {{
3176+
if (axisRe.test(keys[i]) && layout[keys[i]] && typeof layout[keys[i]] === 'object') {{
3177+
var ax = layout[keys[i]];
3178+
delete ax.color;
3179+
delete ax.gridcolor;
3180+
delete ax.linecolor;
3181+
delete ax.zerolinecolor;
3182+
}}
3183+
}}
3184+
}};
3185+
}}
3186+
31083187
// Debug: Check Plotly availability
31093188
console.log('[PyWry] Checking Plotly availability...');
31103189
console.log('[PyWry] window.Plotly:', typeof window.Plotly);

0 commit comments

Comments
 (0)