@@ -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