diff options
author | hackademix <giorgio@maone.net> | 2019-04-30 13:31:49 +0200 |
---|---|---|
committer | hackademix <giorgio@maone.net> | 2019-04-30 13:31:49 +0200 |
commit | 21175a8267aae9d88652fac832a90266d5484cd5 (patch) | |
tree | 3811aa55d0021c7b8eba0fe43c2880c6a954f53a | |
parent | 65c68a4839a05bb8aa24a0444964fa8241bc8673 (diff) |
Display NOSCRIPT elements when scripts are blocked or the data-librejs-display attribute is present.
-rw-r--r-- | main_background.js | 64 | ||||
-rw-r--r-- | test/spec/LibreJSSpec.js | 24 |
2 files changed, 77 insertions, 11 deletions
diff --git a/main_background.js b/main_background.js index f9e7521..0a1a2e9 100644 --- a/main_background.js +++ b/main_background.js @@ -938,16 +938,55 @@ function doc2HTML(doc) { } /** -* Removes noscript tags with name "librejs-path" leaving the inner content to load. +* Shortcut to create a correctly namespaced DOM HTML elements */ -function remove_noscripts(html_doc){ - for(var i = 0; i < html_doc.getElementsByName("librejs-path").length; i++){ - if(html_doc.getElementsByName("librejs-path")[i].tagName == "NOSCRIPT"){ - html_doc.getElementsByName("librejs-path")[i].outerHTML = html_doc.getElementsByName("librejs-path")[i].innerHTML; - } - } +function createHTMLElement(doc, name) { + return doc.createElementNS("http://www.w3.org/1999/xhtml", name); +} - return doc2HTML(html_doc); +/** +* Replace any element with a span having the same content (useful to force +* NOSCRIPT elements to visible the same way as NoScript and uBlock do) +*/ +function forceElement(doc, element) { + let replacement = createHTMLElement(doc, "span"); + replacement.innerHTML = element.innerHTML; + element.replaceWith(replacement); + return replacement; +} + +/** +* Forces displaying any element having the "data-librejs-display" attribute and +* <noscript> elements on pages where LibreJS disabled inline scripts (unless +* they have the "data-librejs-nodisplay" attribute). +*/ +function forceNoscriptElements(doc) { + let shown = 0; + // inspired by NoScript's onScriptDisabled.js + for (let noscript of doc.querySelectorAll("noscript:not([data-librejs-nodisplay])")) { + let replacement = forceElement(doc, noscript); + // emulate meta-refresh + let meta = replacement.querySelector('meta[http-equiv="refresh"]'); + if (meta) { + refresh = true; + doc.head.appendChild(meta); + } + shown++; + } + return shown; +} +/** +* Forces displaying any element having the "data-librejs-display" attribute and +* <noscript> elements on pages where LibreJS disabled inline scripts (unless +* they have the "data-librejs-nodisplay" attribute). +*/ +function showConditionalElements(doc) { + let shown = 0; + for (let element of document.querySelectorAll("[data-librejs-display]")) { + forceElement(doc, element); + shown++; + } + return shown; } /** @@ -1113,10 +1152,13 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){ } } } + + modified = showConditionalElements(html_doc) > 0 || modified; if (modified) { - return modifiedInline - ? await remove_noscripts(html_doc) - : doc2HTML(html_doc); + if (modifiedInline) { + forceNoscriptElements(html_doc); + } + return doc2HTML(html_doc); } } return null; diff --git a/test/spec/LibreJSSpec.js b/test/spec/LibreJSSpec.js index 43f37a7..8d4aebe 100644 --- a/test/spec/LibreJSSpec.js +++ b/test/spec/LibreJSSpec.js @@ -222,6 +222,30 @@ describe("LibreJS' components", () => { expect(processed).toContain(trivialAsUrl); expect(processed).not.toContain(nontrivialAsUrl); }); + + it("should force displaying NOSCRIPT elements (except those with @data-librejs-nodisplay) where scripts have been blocked", async () => { + let noscriptContent = "I'm NOSCRIPT content"; + let asNoscript = `<noscript>${noscriptContent}</noscript>`; + let asNodisplay = `<noscript data-librejs-nodisplay>${noscriptContent}</noscript>`; + let asSpan = `<span>${noscriptContent}</span>`; + let page = addToBody(addToBody(nontrivialInHtml, asNoscript), asNodisplay); + let processed = await processHtml(page); + expect(processed).not.toContain(asNoscript); + expect(processed).toContain(asSpan); + expect(processed).not.toContain(asNodisplay); + }); + + it("should always force displaying @data-librejs-display elements", async () => { + let content = "I'm FORCED content"; + let asDisplay = `<span data-librejs-display>${content}</span>`; + let asSpan = `<span>${content}</span>`; + for (let page of [nontrivialInHtml, "<body></body>"]) { + page = addToBody(page, asDisplay); + let processed = await processHtml(page); + expect(processed).not.toContain(asDisplay); + expect(processed).not.toContain(asSpan); + } + }); }); describe("The external (Web Labels) license checker", () => { |