mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 18:29:21 +00:00 
			
		
		
		
	feat(frontend): rename inj roles to sys-front-*, add sys-svc-cdn, cache-busting lookup
Introduce sys-svc-cdn (cdn_paths/cdn_urls/cdn_dirs) and ensure CDN directories + latest symlink. Rename sys-srv-web-inj-* → sys-front-inj-*; update includes/templates; serve shared/per-app CSS & JS via CDN. Add lookup_plugins/local_mtime_qs.py for mtime-based cache busting; split CSS into default.css/bootstrap.css + optional per-app style.css. CSP: use style-src-elem; drop unsafe-inline for styles. Services: fix SYS_SERVICE_ALL_ENABLED bool and controlled flush. BREAKING CHANGE: role names changed; replace includes and references accordingly. Conversation: https://chatgpt.com/share/68b55494-9ec4-800f-b559-44707029141d
This commit is contained in:
		
							
								
								
									
										1
									
								
								roles/sys-front-inj-desktop/templates/body_sub.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								roles/sys-front-inj-desktop/templates/body_sub.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| <script>{{ iframe_init_code_one_liner }}</script> | ||||
							
								
								
									
										1
									
								
								roles/sys-front-inj-desktop/templates/head_sub.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								roles/sys-front-inj-desktop/templates/head_sub.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| <script src="{{ cdn_urls.shared.js }}/{{ INJ_DESKTOP_JS_FILE_NAME }}{{ lookup('local_mtime_qs', [playbook_dir, 'roles', 'sys-front-inj-desktop', 'templates', INJ_DESKTOP_JS_FILE_NAME ~ '.j2'] | path_join) }}"></script> | ||||
							
								
								
									
										57
									
								
								roles/sys-front-inj-desktop/templates/iframe-handler.js.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								roles/sys-front-inj-desktop/templates/iframe-handler.js.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| (function (global) { | ||||
|   /** | ||||
|    * Initializes the iframe sync & external link forcing logic. | ||||
|    * @param {string} primary_domain | ||||
|    * @param {string} current_domain | ||||
|    * @param {string} allowedOrigin - Parent origin for postMessage | ||||
|    */ | ||||
|   function initIframeHandler(primary_domain, current_domain, allowedOrigin) { | ||||
|     function notifyParent() { | ||||
|       if (window.self !== window.top) { | ||||
|         try { | ||||
|           window.parent.postMessage( | ||||
|             { type: "iframeLocationChange", href: window.location.href }, | ||||
|             allowedOrigin | ||||
|           ); | ||||
|         } catch (e) {} | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     function forceExternalLinks() { | ||||
|       Array.prototype.forEach.call(document.querySelectorAll("a[href]"), function (a) { | ||||
|         try { | ||||
|           var url = new URL(a.href, location); | ||||
|           // open new tab if link goes outside our primary OR current domain | ||||
|           if (!(url.hostname.endsWith(primary_domain) || url.hostname.endsWith(current_domain))) { | ||||
|             a.target = "_blank"; | ||||
|             a.rel = "noopener"; | ||||
|           } | ||||
|         } catch (e) {} | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     window.addEventListener("load", function () { | ||||
|       notifyParent(); | ||||
|       forceExternalLinks(); | ||||
|     }); | ||||
|     window.addEventListener("popstate", function () { | ||||
|       notifyParent(); | ||||
|       forceExternalLinks(); | ||||
|     }); | ||||
|  | ||||
|     // SPA support | ||||
|     var _pushState = history.pushState; | ||||
|     history.pushState = function () { | ||||
|       _pushState.apply(history, arguments); | ||||
|       notifyParent(); | ||||
|       forceExternalLinks(); | ||||
|     }; | ||||
|  | ||||
|     {% if MODE_DEBUG | bool %} | ||||
|     try { console.log("[iframe-sync] initIframeHandler installed."); } catch (e) {} | ||||
|     {% endif %} | ||||
|   } | ||||
|  | ||||
|   // expose for inline bootstrap | ||||
|   global.initIframeHandler = initIframeHandler; | ||||
| })(window); | ||||
| @@ -0,0 +1,10 @@ | ||||
| document.addEventListener('DOMContentLoaded', function () { | ||||
|   initIframeHandler( | ||||
|     '{{ PRIMARY_DOMAIN }}', | ||||
|     '{{ domain }}', | ||||
|     '{{ domains | get_url("web-app-desktop", WEB_PROTOCOL) }}' | ||||
|   ); | ||||
| }); | ||||
| {% if MODE_DEBUG | bool %} | ||||
| try { console.log("[iframe-sync] Sender for iframe messages is active."); } catch(e) {} | ||||
| {% endif %} | ||||
		Reference in New Issue
	
	Block a user