Execute script tags in included HTML so Matomo runs
ci/woodpecker/push/woodpecker Pipeline failed Details

- Recreate and execute <script> tags from header/footer includes and head includes
- Ensures Matomo inline snippet runs when header is injected via includes.js
This commit is contained in:
Leopere 2025-08-07 17:04:31 -04:00
parent 494e4a568e
commit f882ab7d3b
1 changed files with 41 additions and 3 deletions

View File

@ -4,6 +4,33 @@
*/
document.addEventListener('DOMContentLoaded', function() {
// Helper: recreate and execute a <script> element
function recreateAndExecuteScript(originalScriptElement, targetParent) {
const executableScript = document.createElement('script');
// Copy attributes (e.g., src, async, defer)
for (const { name, value } of Array.from(originalScriptElement.attributes)) {
executableScript.setAttribute(name, value);
}
// Inline script content
if (!originalScriptElement.src) {
executableScript.textContent = originalScriptElement.textContent;
}
// Append to target to trigger execution
(targetParent || document.head || document.body).appendChild(executableScript);
}
// Helper: find and execute all scripts within a container element
function executeScriptsInContainer(containerElement, targetParent) {
if (!containerElement) return;
const scriptElements = Array.from(containerElement.querySelectorAll('script'));
scriptElements.forEach((scriptEl) => {
recreateAndExecuteScript(scriptEl, targetParent);
});
}
// Function to include HTML content
async function includeHTML(elementId, filePath, callback) {
try {
@ -12,7 +39,12 @@ document.addEventListener('DOMContentLoaded', function() {
throw new Error(`Failed to load ${filePath}: ${response.status} ${response.statusText}`);
}
const content = await response.text();
document.getElementById(elementId).innerHTML = content;
const targetElement = document.getElementById(elementId);
targetElement.innerHTML = content;
// Ensure any scripts inside included content (e.g., Matomo) are executed
executeScriptsInContainer(targetElement, document.head);
if (callback) callback();
} catch (error) {
console.error('Error including HTML:', error);
@ -30,10 +62,16 @@ document.addEventListener('DOMContentLoaded', function() {
const headElement = document.getElementsByTagName('head')[0];
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
// Append each child from the loaded content to the head
while (tempDiv.firstChild) {
headElement.appendChild(tempDiv.firstChild);
const node = tempDiv.firstChild;
if (node.tagName && node.tagName.toLowerCase() === 'script') {
recreateAndExecuteScript(node, headElement);
node.remove();
} else {
headElement.appendChild(node);
}
}
} catch (error) {
console.error('Error including HTML in head:', error);