1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-12-03 14:59:57 +00:00

Consent banner: Add optional blocking of embedded content until consent granted

This commit is contained in:
jeremy@jermolene.com 2020-07-02 13:14:51 +01:00
parent bd2cf5c464
commit a0db3abe99
10 changed files with 127 additions and 8 deletions

View File

@ -0,0 +1,13 @@
title: $:/plugins/tiddlywiki/consent-banner/blocked-embed-message-wrapper
\define styles()
width:$(width)$;height:$(height)$;
\end
<div class="tc-blocked-embedded-content" style=<<styles>>>
<div class="tc-blocked-embedded-content-inner">
<div class="tc-blocked-embedded-content-inner-inner">
<$transclude tiddler="$:/config/plugins/tiddlywiki/consent-banner/blocked-embed-message" mode="inline"/>
</div>
</div>
</div>

View File

@ -40,3 +40,9 @@ Current status: {{$:/state/consent-banner/accepted}} (blank indicates that conse
<$button message="tm-consent-clear" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/hint}}> <$button message="tm-consent-clear" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/caption}} {{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/caption}}
</$button> </$button>
! Embedded Content Blocking
//Requires page reload//
<$checkbox tiddler="$:/config/plugins/tiddlywiki/consent-banner/block-embedded-content" field="text" checked="yes" unchecked="no" default="no"> Block all embedded content such as &lt;iframe>, &lt;embed> and &lt;object> unless consent has been granted</$checkbox>

View File

@ -0,0 +1,2 @@
title: $:/config/plugins/tiddlywiki/consent-banner/block-embedded-content
text: yes

View File

@ -0,0 +1,7 @@
title: $:/config/plugins/tiddlywiki/consent-banner/blocked-embed-message
Blocked embedded content from<br/><a href=<<url>> class="tc-tiddlylink-external" target="_blank" rel="noopener noreferrer"><$text text=<<url>>/></a>
<hr/>
{{$:/plugins/tiddlywiki/consent-banner/buttons/accept}} cookies to unblock

View File

@ -0,0 +1,4 @@
title: $:/plugins/tiddlywiki/consent-banner/tv-block-embedded-content
tags: $:/tags/Macro
<$set name="tv-block-embedded-content" value={{{ [{$:/config/cookie-consent-required}else[no]match[yes]then{$:/state/consent-banner/accepted}!match[yes]then[yes]] }}}/>

View File

@ -24,6 +24,16 @@ Add these entries to your current colour palette to change the colours used by t
* ''consent-banner-hr-background'' - the background colour of horizontal rules within the consent banner (defaults to {{$:/config/DefaultColourMappings/consent-banner-hr-background}}) * ''consent-banner-hr-background'' - the background colour of horizontal rules within the consent banner (defaults to {{$:/config/DefaultColourMappings/consent-banner-hr-background}})
* ''consent-banner-link-foreground'' - the foreground colour of tiddler links within the consent banner (defaults to {{$:/config/DefaultColourMappings/consent-banner-link-foreground}}) * ''consent-banner-link-foreground'' - the foreground colour of tiddler links within the consent banner (defaults to {{$:/config/DefaultColourMappings/consent-banner-link-foreground}})
! Embedded Content Blocking
Unless disabled via the config tab, content embedded via &lt;iframe>, &lt;embed> or &lt;object> is blocked until the user consents to accept cookies.
!! Implementation Details
Embedded content is blocked if the variable `tv-block-embedded-content` is set to `yes`. It is set to the current consent status by a [[global macro|$:/plugins/tiddlywiki/consent-banner/tv-block-embedded-content]]:
<$codeblock code={{$:/plugins/tiddlywiki/consent-banner/tv-block-embedded-content}}/>
! ~YouTube macro ! ~YouTube macro
A simple macro for embedding ~YouTube videos is provided to show how to adapt content according to whether consent has been granted. It works by checking the tiddler [[$:/state/consent-banner/accepted]] for the following values: A simple macro for embedding ~YouTube videos is provided to show how to adapt content according to whether consent has been granted. It works by checking the tiddler [[$:/state/consent-banner/accepted]] for the following values:

View File

@ -1,6 +1,10 @@
title: $:/plugins/tiddlywiki/consent-banner/readme title: $:/plugins/tiddlywiki/consent-banner/readme
The ''consent-banner'' plugin helps make websites that are compliant with "cookie legislation" such as the [[EU General Data Protection Regulation|https://gdpr.eu/cookies/]]. The ''consent-banner'' plugin helps make websites that are compliant with "cookie legislation" such as the [[EU General Data Protection Regulation|https://gdpr.eu/cookies/]].
This plugin presents a banner inviting the user to accept or reject cookies, keeping track of their consent in local storage so that the banner can be hidden on subsequent visits. Consent status is also available via a configuration tiddler so that it is possible to construct content that behaves differently depending upon whether consent has been granted. As an example, a macro is provided for embedding ~YouTube videos that automatically uses the youtube-nocookie.com variant of video URLs unless the user has accepted cookies. It presents a banner inviting the user to accept or reject cookies, keeping track of their consent in local storage so that the banner can be hidden on subsequent visits.
By default, content embedded with &lt;iframe>, &lt;embed> and &lt;object> is blocked unless the user consents to accept cookies.
Consent status is available via a configuration tiddler so that it is possible to construct content that behaves differently depending upon whether consent has been granted. As an example, a macro is provided for embedding ~YouTube videos that automatically uses the youtube-nocookie.com variant of video URLs unless the user has accepted cookies.
Please note that using this plugin does not guarantee compliance with any particular legislation. You will need to understand the technical issues specific to your situation, and if necessary seek legal advice. Please note that using this plugin does not guarantee compliance with any particular legislation. You will need to understand the technical issues specific to your situation, and if necessary seek legal advice.

View File

@ -16,16 +16,18 @@ Startup initialisation
exports.name = "consent-banner"; exports.name = "consent-banner";
exports.platforms = ["browser"]; exports.platforms = ["browser"];
exports.after = ["startup"]; exports.after = ["startup"];
exports.before = ["render"];
exports.synchronous = true; exports.synchronous = true;
var CHECK_CONSENT_INTERVAL = 1000, // Milliseconds between checking local storage var CHECK_CONSENT_INTERVAL = 1000, // Milliseconds between checking local storage
IS_LOGGED_IN_TITLE = "$:/status/IsLoggedIn", IS_LOGGED_IN_TITLE = "$:/status/IsLoggedIn",
CONSENT_KEY = "COOKIE_CONSENT", // Local storage keyname CONSENT_KEY = "COOKIE_CONSENT", // Local storage keyname
CONSENT_TITLE = "$:/state/consent-banner/accepted"; // "": undeclared, "yes": accepted, "no": declined CONSENT_TITLE = "$:/state/consent-banner/accepted", // "": undeclared, "yes": accepted, "no": declined
CONFIG_BLOCK_EMBEDDED_CONTENT_TITLE = "$:/config/plugins/tiddlywiki/consent-banner/block-embedded-content",
EMBEDDED_MESSAGE_WRAPPER_TITLE = "$:/plugins/tiddlywiki/consent-banner/blocked-embed-message-wrapper";
exports.startup = function() { exports.startup = function() {
var self = this, var consentState = "",
consentState = "",
setConsentStatus = function(state) { setConsentStatus = function(state) {
if(consentState !== state) { if(consentState !== state) {
consentState = state; consentState = state;
@ -51,9 +53,9 @@ exports.startup = function() {
pollConsentStatus = function() { pollConsentStatus = function() {
setTimeout(checkConsentStatus,CHECK_CONSENT_INTERVAL); setTimeout(checkConsentStatus,CHECK_CONSENT_INTERVAL);
}; };
// Set the current constant status // Set the current consent status
checkConsentStatus(); checkConsentStatus();
// Listen for tm-clear-browser-storage messages // Listen for consent messages
$tw.rootWidget.addEventListener("tm-consent-accept",function(event) { $tw.rootWidget.addEventListener("tm-consent-accept",function(event) {
setConsentStatus("yes"); setConsentStatus("yes");
}); });
@ -63,6 +65,43 @@ exports.startup = function() {
$tw.rootWidget.addEventListener("tm-consent-clear",function(event) { $tw.rootWidget.addEventListener("tm-consent-clear",function(event) {
setConsentStatus(""); setConsentStatus("");
}); });
// Add our element rendering hook
if($tw.wiki.getTiddlerText(CONFIG_BLOCK_EMBEDDED_CONTENT_TITLE,"no") === "yes") {
$tw.hooks.addHook("th-rendering-element",function(parseTreeNodes,widget) {
if(parseTreeNodes) {
return parseTreeNodes;
}
if(["iframe","object","embed"].indexOf(widget.tag) !== -1 && widget.getVariable("tv-block-embedded-content","no") === "yes") {
var url = widget.getAttribute("src"),
addUnitsIfMissing = function(str) {
str = "" + str;
return str + (("" + parseInt(str,10)) === str ? "px" : "");
},
width = addUnitsIfMissing(widget.getAttribute("width","")),
height = addUnitsIfMissing(widget.getAttribute("height",""));
return [
{
type: "vars",
attributes: {
url: {type: "string", value: url},
width: {type: "string", value: width},
height: {type: "string", value: height}
},
children: [
{
type: "transclude",
attributes: {
tiddler: {type: "string", value: EMBEDDED_MESSAGE_WRAPPER_TITLE},
mode: {type: "string", value: "inline"}
}
}
]
}
];
}
return null;
});
}
}; };
})(); })();

View File

@ -56,9 +56,12 @@ tags: $:/tags/Stylesheet
} }
.tc-consent-banner .tc-consent-button {
margin-right: 1em;
}
.tc-consent-button { .tc-consent-button {
border: 1px solid <<colour consent-banner-button-border>>; border: 1px solid <<colour consent-banner-button-border>>;
margin-right: 1em;
margin-top: 1em; margin-top: 1em;
padding: 0.75em 1.5em; padding: 0.75em 1.5em;
color: <<colour consent-banner-button-foreground>>; color: <<colour consent-banner-button-foreground>>;
@ -77,3 +80,32 @@ tags: $:/tags/Stylesheet
color: <<colour consent-banner-button-default-foreground>>; color: <<colour consent-banner-button-default-foreground>>;
background: <<colour consent-banner-button-default-background>>; background: <<colour consent-banner-button-default-background>>;
} }
.tc-blocked-embedded-content {
display: inline-block;
overflow: hidden;
color: <<colour background>>;
background: <<colour muted-foreground>>;
border: 1px solid <<colour foreground>>;
<<box-shadow "inset 0 0 8px rgba(0, 0, 0, 0.15)">>
}
.tc-blocked-embedded-content-inner {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.tc-blocked-embedded-content-inner-inner {
display: inline-block;
text-align: center;
}
.tc-blocked-embedded-content-inner-inner hr {
background: <<colour foreground>>;
height: 1px;
width: 80%;
border: none;
}

View File

@ -2,12 +2,14 @@ title: $:/plugins/tiddlywiki/consent-banner/youtube
tags: $:/tags/Macro tags: $:/tags/Macro
\define embed-video-with-consent(code) \define embed-video-with-consent(code)
<$set name="tv-block-embedded-content" value="no">
<$reveal state="$:/state/consent-banner/accepted" type="match" text="yes" tag="div"> <$reveal state="$:/state/consent-banner/accepted" type="match" text="yes" tag="div">
<iframe width="560" height="315" src="https://www.youtube.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</$reveal> </$reveal>
<$reveal state="$:/state/consent-banner/accepted" type="nomatch" text="yes" tag="div"> <$reveal state="$:/state/consent-banner/accepted" type="nomatch" text="yes" tag="div">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</$reveal> </$reveal>
</$set>
\end \end
! Macro source ! Macro source