diff --git a/internal/template/templates/common/layout.html b/internal/template/templates/common/layout.html index 5aaf03436b7..df7ca724e05 100644 --- a/internal/template/templates/common/layout.html +++ b/internal/template/templates/common/layout.html @@ -39,7 +39,7 @@ {{ else }} - + {{ end }} diff --git a/internal/ui/static/js/app.js b/internal/ui/static/js/app.js index 99145d497d3..7bac8bd9880 100644 --- a/internal/ui/static/js/app.js +++ b/internal/ui/static/js/app.js @@ -114,7 +114,7 @@ function handleSubmitButtons() { let button = element.querySelector("button"); if (button) { - button.innerHTML = button.dataset.labelLoading; + button.textContent = button.dataset.labelLoading; button.disabled = true; } }; @@ -206,7 +206,7 @@ function toggleEntryStatus(element, toasting) { let currentStatus = link.dataset.value; let newStatus = currentStatus === "read" ? "unread" : "read"; - link.querySelector("span").innerHTML = link.dataset.labelLoading; + link.querySelector("span").textContent = link.dataset.labelLoading; updateEntriesStatus([entryID], newStatus, () => { let iconElement, label; @@ -284,6 +284,14 @@ function handleSaveEntry(element) { } } +// Set the span-child of `element` to contain `label`. +function changeSpanLabel(element, label) { + let span = document.createElement('span'); + span.classList.add('icon-label'); + span.textContent = label; + element.appendChild(span); +} + // Send the Ajax request to save an entry. function saveEntry(element, toasting) { if (!element) { @@ -294,11 +302,14 @@ function saveEntry(element, toasting) { return; } - element.innerHTML = '' + element.dataset.labelLoading + ''; + + element.textContent = '' + changeSpanLabel(element, element.dataset.labelLoading); let request = new RequestBuilder(element.dataset.saveUrl); request.withCallback(() => { - element.innerHTML = '' + element.dataset.labelDone + ''; + element.textContent = '' + changeSpanLabel(element, element.dataset.labelDone); element.dataset.completed = true; if (toasting) { let iconElement = document.querySelector("template#icon-save"); @@ -324,7 +335,8 @@ function toggleBookmark(parentElement, toasting) { return; } - element.innerHTML = '' + element.dataset.labelLoading + ''; + element.textContent = '' + changeSpanLabel(element, element.dataset.labelLoading); let request = new RequestBuilder(element.dataset.bookmarkUrl); request.withCallback(() => { @@ -348,8 +360,12 @@ function toggleBookmark(parentElement, toasting) { } } - element.innerHTML = iconElement.innerHTML + '' + label + ''; + element.textContent = ''; + let newIcon = iconElement.content.cloneNode(true); + element.appendChild(newIcon); + changeSpanLabel(element, label); element.dataset.value = newStarStatus; + //debugger; }); request.execute(); } @@ -365,19 +381,23 @@ function handleFetchOriginalContent() { return; } - let previousInnerHTML = element.innerHTML; - element.innerHTML = '' + element.dataset.labelLoading + ''; + //let previousInnerHTML = element.innerHTML; + let previousElement = element.cloneNode(true) + element.textContent = '' + changeSpanLabel(element, element.dataset.labelLoading); let request = new RequestBuilder(element.dataset.fetchContentUrl); request.withCallback((response) => { - element.innerHTML = previousInnerHTML; + //element.innerHTML = previousInnerHTML; + element.textContent = ''; + element.appendChild(previousElement); response.json().then((data) => { if (data.hasOwnProperty("content") && data.hasOwnProperty("reading_time")) { - document.querySelector(".entry-content").innerHTML = data.content; + document.querySelector(".entry-content").innerHTML = ttpolicy.createHTML(data.content); let entryReadingtimeElement = document.querySelector(".entry-reading-time"); if (entryReadingtimeElement) { - entryReadingtimeElement.innerHTML = data.reading_time; + entryReadingtimeElement.innerHTML = ttpolicy.createHTML(data.reading_time); } } }); @@ -654,7 +674,10 @@ function showToast(label, iconElement) { const toastMsgElement = document.getElementById("toast-msg"); if (toastMsgElement) { - toastMsgElement.innerHTML = iconElement.innerHTML + '' + label + ''; + toastMsgElement.textContent = '' + let newIcon = iconElement.content.cloneNode(true); + element.appendChild(newIcon); + changeSpanLabel(toastMsgElement, label); const toastElementWrapper = document.getElementById("toast-wrapper"); if (toastElementWrapper) { diff --git a/internal/ui/static/js/bootstrap.js b/internal/ui/static/js/bootstrap.js index cd11008e26b..b238128a34a 100644 --- a/internal/ui/static/js/bootstrap.js +++ b/internal/ui/static/js/bootstrap.js @@ -126,7 +126,7 @@ document.addEventListener("DOMContentLoaded", () => { if ("serviceWorker" in navigator) { let scriptElement = document.getElementById("service-worker-script"); if (scriptElement) { - navigator.serviceWorker.register(scriptElement.src); + navigator.serviceWorker.register(ttpolicy.createScriptURL('')); } } diff --git a/internal/ui/static/js/trusted_types.js b/internal/ui/static/js/trusted_types.js new file mode 100644 index 00000000000..e7289e05184 --- /dev/null +++ b/internal/ui/static/js/trusted_types.js @@ -0,0 +1,5 @@ +//TODO: this is catastrophic +const ttpolicy = trustedTypes.createPolicy("ttpolicy", { + createScriptURL: () => document.getElementById("service-worker-script").src, + createHTML : (data) => data, +}); diff --git a/internal/ui/static/static.go b/internal/ui/static/static.go index a3deb6d9d95..2f46c30373e 100644 --- a/internal/ui/static/static.go +++ b/internal/ui/static/static.go @@ -112,6 +112,7 @@ func GenerateStylesheetsBundles() error { func GenerateJavascriptBundles() error { var bundles = map[string][]string{ "app": { + "js/trusted_types.js", "js/dom_helper.js", "js/touch_handler.js", "js/keyboard_handler.js",