middleman-gdpr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 644b704a5ba83280c4d287fa1f271ac3c0a938db390c6086d98a1d58b1e486ed
4
+ data.tar.gz: 46b00fd0a01b1f24e96244602209e0ca450047e929dd219371a7ef0f0a4c59a0
5
+ SHA512:
6
+ metadata.gz: 01b92206c792ebdbb447fb06197a8fbdfc9c3e3ba69d43e7af270c7e54e4ea01b954d54c9a8ccc4e0968b41873f97e58960641a81db2c7467c5767ffb1d3b384
7
+ data.tar.gz: 6ff5caee0f6e04ace4b7cf5ebc475b5067cfde9ff70817f8585e581a374a75913296e1adfdd150d596676659dce71accbac46db9816086ab742551508077be93
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Les Poupées Russes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,65 @@
1
+ # Middleman GDPR
2
+ Helps getting your Middleman website GDPR compliant
3
+
4
+ ## Installation
5
+ Add this line to your Gemfile:
6
+
7
+ ```ruby
8
+ gem 'middleman-gdpr'
9
+ ```
10
+
11
+ And then execute:
12
+ ```bash
13
+ $ bundle
14
+ ```
15
+
16
+ Or install it yourself as:
17
+ ```bash
18
+ $ gem install middleman-gdpr
19
+ ```
20
+
21
+ Activate [Sprockets](https://github.com/middleman/middleman-sprockets) and [I18n](https://middlemanapp.com/advanced/localization/):
22
+ ```ruby
23
+ # config.rb
24
+ activate :sprockets
25
+ activate :i18n
26
+ ```
27
+
28
+ Add this to the layout:
29
+ ```ruby
30
+ <%= gdpr %>
31
+ ```
32
+
33
+ Add this to javascripts:
34
+ ```js
35
+ //= require gdpr/cookie_consent
36
+ ```
37
+
38
+ Add this to stylesheets:
39
+ ```sass
40
+ @import 'gdpr/cookie_consent'
41
+ ```
42
+
43
+ Set the privacy policy url in the locales.
44
+
45
+ ## Checklist
46
+
47
+ https://www.eugdpr.org/
48
+
49
+ - [x] Cookie consent
50
+ - [ ] Privacy policy
51
+ - [ ] There must be an optin
52
+ - [ ] Optin must be unchecked by default
53
+ - [ ] Account must be deletable
54
+ - [ ] Users must have access to their data
55
+ - [ ] Users must be able to modify their data
56
+
57
+ ## Thanks
58
+
59
+ Inspired by cookies_eu (https://github.com/infinum/cookies_eu), thank you :)
60
+
61
+ ## Contributing
62
+ Feel free to pull request!
63
+
64
+ ## License
65
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Gdpr'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+ require 'rake/testtask'
19
+
20
+ Rake::TestTask.new(:test) do |t|
21
+ t.libs << 'test'
22
+ t.pattern = 'test/**/*_test.rb'
23
+ t.verbose = false
24
+ end
25
+
26
+ task default: :test
@@ -0,0 +1,14 @@
1
+ require 'middleman-sprockets'
2
+
3
+ module Middleman
4
+ module Gdpr
5
+
6
+ end
7
+ end
8
+
9
+ Middleman::Extensions.register :gdpr do
10
+ require 'middleman-gdpr/version'
11
+ require 'middleman-gdpr/extension'
12
+
13
+ Middleman::Gdpr::Extension
14
+ end
@@ -0,0 +1,51 @@
1
+ module Middleman
2
+ module Gdpr
3
+ class Extension < Extension
4
+ # def initialize(app, options_hash={}, &block)
5
+ # super
6
+ # end
7
+
8
+ def after_configuration
9
+ puts "\e[91mGDPR: Sprockets extension not found, GDPR extension has not been activated\e[39m" and return if sprockets.blank?
10
+ puts "\e[91mGDPR: I18n extension not found, GDPR extension has not been activated\e[39m" and return if i18n.blank?
11
+
12
+ ['source/stylesheets', 'source/javascripts', 'node_modules'].each do |path|
13
+ sprockets.environment.append_path root + path
14
+ end
15
+
16
+ I18n.load_path.concat Dir[root + 'locales/*.yml']
17
+ end
18
+
19
+ def root
20
+ Pathname.new(__dir__) + '../..'
21
+ end
22
+
23
+ helpers do
24
+ def gdpr
25
+ <<~HTML
26
+ <div class="gdpr__cookie_consent js-gdpr__cookie_consent">
27
+ <div class="gdpr__cookie_consent__text">
28
+ #{t 'gdpr.cookie_consent.text'}
29
+ <br />
30
+ #{t 'gdpr.cookie_consent.learn_more_html', link: t('gdpr.privacy_policy')}
31
+ </div>
32
+ <div class="gdpr__cookie_consent__buttons">
33
+ <button class="gdpr__cookie_consent__buttons__ok js-gdpr__cookie_consent__buttons__ok"> #{t 'gdpr.cookie_consent.button' }</button>
34
+ </div>
35
+ </div>
36
+ HTML
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def sprockets
43
+ @app.extensions[:sprockets]
44
+ end
45
+
46
+ def i18n
47
+ @app.extensions[:i18n]
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module Gdpr
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require 'middleman-gdpr'
@@ -0,0 +1,7 @@
1
+ de:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: "Indem Sie Ihre Navigation auf dieser Website fortsetzen, akzeptieren Sie die Verwendung von Cookies, die insbesondere dazu dienen, Ihnen personalisierte Funktionen anzubieten und Ihre Besuche auf der Website zu erfassen."
6
+ button: "Ich habe verstanden"
7
+ learn_more_html: "Für weitere Informationen und Einstellen der Cookies : <a href=\"%{link}\" target=\"_blank\">bitte hier klicken</a>"
@@ -0,0 +1,7 @@
1
+ en:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: 'By navigating on this website, you agree to our use of cookies to personalize certain website features and to measure the audience and use of this website.'
6
+ button: "I agree"
7
+ learn_more_html: "To learn more about cookies and how to customize your cookies options: <a href=\"%{link}\" target=\"_blank\">click here</a>"
@@ -0,0 +1,7 @@
1
+ es:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: "Al continuar su navegación por este sitio, acepta la utilización de cookies, que tienen por objeto proponerle funcionalidades personalizadas y realizar mediciones de audiencia."
6
+ button: "Entendido"
7
+ learn_more_html: "Para saber más y definir la configuración de estas cookies: <a href=\"%{link}\" target=\"_blank\">hacer clic aquí</a>"
@@ -0,0 +1,7 @@
1
+ fr:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: "En poursuivant votre navigation sur ce site, vous acceptez l’utilisation de Cookies pour vous proposer notamment des fonctionnalités personnalisées et pour réaliser des mesures d’audience."
6
+ button: "J'ai compris"
7
+ learn_more_html: "Pour en savoir plus et paramétrer ces cookies : <a href=\"%{link}\" target=\"_blank\">cliquer ici</a>"
@@ -0,0 +1,7 @@
1
+ it:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: "Proseguendo nella navigazione del Sito, l'utente acconsente all'utilizzo dei cookie allo scopo di fornire funzioni personalizzate e di misurazione dell'audience."
6
+ button: "Ho capito"
7
+ learn_more_html: "Per maggiori informazioni e per configurare i cookie: <a href=\"%{link}\" target=\"_blank\">cliccare qui</a>"
@@ -0,0 +1,7 @@
1
+ zh:
2
+ gdpr:
3
+ privacy_policy: https://www.eugdpr.org
4
+ cookie_consent:
5
+ text: '在瀏覽本網站之時,您同意本網站收集閣下Cookies(如有)及用於獲取配置數據以及分析上網認識的瀏覽習慣。Cookies可免除閣下每次瀏覽網站是重新登記的麻煩,並追蹤閣下喜歡的網頁主題選項,為閣下提供更個性化服務。阁下如不希望接受Cookies,可以修改有关互联网选项或阁下计算机系统的浏览选项,但阁下可能因此无法使用或启动本网站的若干功能。'
6
+ button: "同意"
7
+ learn_more_html: "<a href=\"%{link}\" target=\"_blank\">關於Cookies以及設置閣下計算機系統的瀏</a>"
@@ -0,0 +1,79 @@
1
+ ## Issues
2
+
3
+ - Report issues or feature requests on [GitHub Issues](https://github.com/js-cookie/js-cookie/issues).
4
+ - If reporting a bug, please add a [simplified example](http://sscce.org/).
5
+
6
+ ## Pull requests
7
+ - Create a new topic branch for every separate change you make.
8
+ - Create a test case if you are fixing a bug or implementing an important feature.
9
+ - Make sure the build runs successfully.
10
+
11
+ ## Development
12
+
13
+ ### Tools
14
+ We use the following tools for development:
15
+
16
+ - [Qunit](http://qunitjs.com/) for tests.
17
+ - [NodeJS](http://nodejs.org/download/) required to run grunt.
18
+ - [Grunt](http://gruntjs.com/getting-started) for task management.
19
+
20
+ ### Getting started
21
+ Install [NodeJS](http://nodejs.org/).
22
+ Install globally grunt-cli using the following command:
23
+
24
+ $ npm install -g grunt-cli
25
+
26
+ Browse to the project root directory and install the dev dependencies:
27
+
28
+ $ npm install -d
29
+
30
+ To execute the build and tests run the following command in the root of the project:
31
+
32
+ $ grunt
33
+
34
+ You should see a green message in the console:
35
+
36
+ Done, without errors.
37
+
38
+ ### Tests
39
+ You can also run the tests in the browser.
40
+ Start a test server from the project root:
41
+
42
+ $ grunt connect:tests
43
+
44
+ This will automatically open the test suite at http://127.0.0.1:10000 in the default browser, with livereload enabled.
45
+
46
+ _Note: we recommend cleaning all the browser cookies before running the tests, that can avoid false positive failures._
47
+
48
+ ### Automatic build
49
+ You can build automatically after a file change using the following command:
50
+
51
+ $ grunt watch
52
+
53
+ ## Integration with server-side
54
+
55
+ js-cookie allows integrating the encoding test suite with solutions written in other server-side languages. To integrate successfully, the server-side solution need to execute the `test/encoding.html` file in it's integration testing routine with a web automation tool, like [Selenium](http://www.seleniumhq.org/). js-cookie test suite exposes an API to make this happen.
56
+
57
+ ### ?integration_baseurl
58
+
59
+ Specify the base url to pass the cookies into the server through a query string. If `integration_baseurl` query is not present, then js-cookie will assume there's no server.
60
+
61
+ ### window.global_test_results
62
+
63
+ After the test suite has finished, js-cookie exposes the global `window.global_test_results` property containing an Object Literal that represents the [QUnit's details](http://api.qunitjs.com/QUnit.done/). js-cookie also adds an additional property representing an Array containing the tests data.
64
+
65
+ ### Handling requests
66
+
67
+ When js-cookie encoding tests are executed, it will request a url in the server through an iframe representing each test being run. js-cookie expects the server to handle the input and return the proper `Set-Cookie` headers in the response. js-cookie will then read the response and verify if the encoding is consistent with js-cookie default encoding mechanism
68
+
69
+ js-cookie will send some requests to the server from the baseurl in the format `/encoding?name=<cookie>`, where `<cookie>` represents the cookie-name to be read from the request.
70
+
71
+ The server should handle those requests, internally parsing the cookie from the request and writing it again. It must set an `application/json` content type containing an object literal in the content body with `name` and `value` keys, each representing the cookie-name and cookie-value decoded by the server-side implementation.
72
+
73
+ If the server fails to respond with this specification in any request, the related QUnit test will fail. This is to make sure the server-side implementation will always be in sync with js-cookie encoding tests for maximum compatibility.
74
+
75
+ ### Projects using it
76
+
77
+ This hook is being used in the following projects:
78
+
79
+ * [Java Cookie](https://github.com/js-cookie/java-cookie).
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Klaus Hartl
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,304 @@
1
+ <p align="center">
2
+ <img src="https://cloud.githubusercontent.com/assets/835857/14581711/ba623018-0436-11e6-8fce-d2ccd4d379c9.gif">
3
+ </p>
4
+
5
+ # JavaScript Cookie [![Build Status](https://travis-ci.org/js-cookie/js-cookie.svg?branch=master)](https://travis-ci.org/js-cookie/js-cookie) [![Code Climate](https://codeclimate.com/github/js-cookie/js-cookie.svg)](https://codeclimate.com/github/js-cookie/js-cookie) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/js-cookie/badge?style=rounded)](https://www.jsdelivr.com/package/npm/js-cookie)
6
+
7
+ A simple, lightweight JavaScript API for handling cookies
8
+
9
+ * Works in [all](https://saucelabs.com/u/js-cookie) browsers
10
+ * Accepts [any](#encoding) character
11
+ * [Heavily](test) tested
12
+ * No dependency
13
+ * [Unobtrusive](#json) JSON support
14
+ * Supports AMD/CommonJS
15
+ * [RFC 6265](https://tools.ietf.org/html/rfc6265) compliant
16
+ * Useful [Wiki](https://github.com/js-cookie/js-cookie/wiki)
17
+ * Enable [custom encoding/decoding](#converters)
18
+ * **~900 bytes** gzipped!
19
+
20
+ **If you're viewing this at https://github.com/js-cookie/js-cookie, you're reading the documentation for the master branch.
21
+ [View documentation for the latest release.](https://github.com/js-cookie/js-cookie/tree/latest#readme)**
22
+
23
+ ## Build Status Matrix
24
+
25
+ [![Selenium Test Status](https://saucelabs.com/browser-matrix/js-cookie.svg)](https://saucelabs.com/u/js-cookie)
26
+
27
+ ## Installation
28
+
29
+ ### Direct download
30
+
31
+ Download the script [here](https://github.com/js-cookie/js-cookie/blob/latest/src/js.cookie.js) and include it (unless you are packaging scripts somehow else):
32
+
33
+ ```html
34
+ <script src="/path/to/js.cookie.js"></script>
35
+ ```
36
+
37
+ Or include it via [jsDelivr CDN](https://www.jsdelivr.com/package/npm/js-cookie):
38
+
39
+ ```html
40
+ <script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
41
+ ```
42
+
43
+ **Do not include the script directly from GitHub (http://raw.github.com/...).** The file is being served as text/plain and as such being blocked
44
+ in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN.
45
+
46
+ ### Package Managers
47
+
48
+ JavaScript Cookie supports [npm](https://www.npmjs.com/package/js-cookie) and [Bower](http://bower.io/search/?q=js-cookie) under the name `js-cookie`.
49
+
50
+ ### Module Loaders
51
+
52
+ JavaScript Cookie can also be loaded as an AMD, CommonJS or [ES6](https://github.com/js-cookie/js-cookie/issues/233#issuecomment-233187386) module.
53
+
54
+ ## Basic Usage
55
+
56
+ Create a cookie, valid across the entire site:
57
+
58
+ ```javascript
59
+ Cookies.set('name', 'value');
60
+ ```
61
+
62
+ Create a cookie that expires 7 days from now, valid across the entire site:
63
+
64
+ ```javascript
65
+ Cookies.set('name', 'value', { expires: 7 });
66
+ ```
67
+
68
+ Create an expiring cookie, valid to the path of the current page:
69
+
70
+ ```javascript
71
+ Cookies.set('name', 'value', { expires: 7, path: '' });
72
+ ```
73
+
74
+ Read cookie:
75
+
76
+ ```javascript
77
+ Cookies.get('name'); // => 'value'
78
+ Cookies.get('nothing'); // => undefined
79
+ ```
80
+
81
+ Read all visible cookies:
82
+
83
+ ```javascript
84
+ Cookies.get(); // => { name: 'value' }
85
+ ```
86
+
87
+ Delete cookie:
88
+
89
+ ```javascript
90
+ Cookies.remove('name');
91
+ ```
92
+
93
+ Delete a cookie valid to the path of the current page:
94
+
95
+ ```javascript
96
+ Cookies.set('name', 'value', { path: '' });
97
+ Cookies.remove('name'); // fail!
98
+ Cookies.remove('name', { path: '' }); // removed!
99
+ ```
100
+
101
+ *IMPORTANT! when deleting a cookie, you must pass the exact same path and domain attributes that was used to set the cookie, unless you're relying on the [default attributes](#cookie-attributes).*
102
+
103
+ *Note: Removing unexisting cookie does not raise any exception nor return any value*
104
+
105
+ ## Namespace conflicts
106
+
107
+ If there is any danger of a conflict with the namespace `Cookies`, the `noConflict` method will allow you to define a new namespace and preserve the original one. This is especially useful when running the script on third party sites e.g. as part of a widget or SDK.
108
+
109
+ ```javascript
110
+ // Assign the js-cookie api to a different variable and restore the original "window.Cookies"
111
+ var Cookies2 = Cookies.noConflict();
112
+ Cookies2.set('name', 'value');
113
+ ```
114
+
115
+ *Note: The `.noConflict` method is not necessary when using AMD or CommonJS, thus it is not exposed in those environments.*
116
+
117
+ ## JSON
118
+
119
+ js-cookie provides unobtrusive JSON storage for cookies.
120
+
121
+ When creating a cookie you can pass an Array or Object Literal instead of a string in the value. If you do so, js-cookie will store the string representation of the object according to `JSON.stringify`:
122
+
123
+ ```javascript
124
+ Cookies.set('name', { foo: 'bar' });
125
+ ```
126
+
127
+ When reading a cookie with the default `Cookies.get` api, you receive the string representation stored in the cookie:
128
+
129
+ ```javascript
130
+ Cookies.get('name'); // => '{"foo":"bar"}'
131
+ ```
132
+
133
+ ```javascript
134
+ Cookies.get(); // => { name: '{"foo":"bar"}' }
135
+ ```
136
+
137
+ When reading a cookie with the `Cookies.getJSON` api, you receive the parsed representation of the string stored in the cookie according to `JSON.parse`:
138
+
139
+ ```javascript
140
+ Cookies.getJSON('name'); // => { foo: 'bar' }
141
+ ```
142
+
143
+ ```javascript
144
+ Cookies.getJSON(); // => { name: { foo: 'bar' } }
145
+ ```
146
+
147
+ *Note: To support IE6-7 ([and IE 8 compatibility mode](http://stackoverflow.com/questions/4715373/json-object-undefined-in-internet-explorer-8)) you need to include the JSON-js polyfill: https://github.com/douglascrockford/JSON-js*
148
+
149
+ ## Encoding
150
+
151
+ This project is [RFC 6265](http://tools.ietf.org/html/rfc6265#section-4.1.1) compliant. All special characters that are not allowed in the cookie-name or cookie-value are encoded with each one's UTF-8 Hex equivalent using [percent-encoding](http://en.wikipedia.org/wiki/Percent-encoding).
152
+ The only character in cookie-name or cookie-value that is allowed and still encoded is the percent `%` character, it is escaped in order to interpret percent input as literal.
153
+ Please note that the default encoding/decoding strategy is meant to be interoperable [only between cookies that are read/written by js-cookie](https://github.com/js-cookie/js-cookie/pull/200#discussion_r63270778). To override the default encoding/decoding strategy you need to use a [converter](#converters).
154
+
155
+ ## Cookie Attributes
156
+
157
+ Cookie attributes defaults can be set globally by setting properties of the `Cookies.defaults` object or individually for each call to `Cookies.set(...)` by passing a plain object in the last argument. Per-call attributes override the default attributes.
158
+
159
+ ### expires
160
+
161
+ Define when the cookie will be removed. Value can be a [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) which will be interpreted as days from time of creation or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) instance. If omitted, the cookie becomes a session cookie.
162
+
163
+ To create a cookie that expires in less than a day, you can check the [FAQ on the Wiki](https://github.com/js-cookie/js-cookie/wiki/Frequently-Asked-Questions#expire-cookies-in-less-than-a-day).
164
+
165
+ **Default:** Cookie is removed when the user closes the browser.
166
+
167
+ **Examples:**
168
+
169
+ ```javascript
170
+ Cookies.set('name', 'value', { expires: 365 });
171
+ Cookies.get('name'); // => 'value'
172
+ Cookies.remove('name');
173
+ ```
174
+
175
+ ### path
176
+
177
+ A [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) indicating the path where the cookie is visible.
178
+
179
+ **Default:** `/`
180
+
181
+ **Examples:**
182
+
183
+ ```javascript
184
+ Cookies.set('name', 'value', { path: '' });
185
+ Cookies.get('name'); // => 'value'
186
+ Cookies.remove('name', { path: '' });
187
+ ```
188
+
189
+ **Note regarding Internet Explorer:**
190
+
191
+ > Due to an obscure bug in the underlying WinINET InternetGetCookie implementation, IE’s document.cookie will not return a cookie if it was set with a path attribute containing a filename.
192
+
193
+ (From [Internet Explorer Cookie Internals (FAQ)](http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx))
194
+
195
+ This means one cannot set a path using `path: window.location.pathname` in case such pathname contains a filename like so: `/check.html` (or at least, such cookie cannot be read correctly).
196
+
197
+ ### domain
198
+
199
+ A [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) indicating a valid domain where the cookie should be visible. The cookie will also be visible to all subdomains.
200
+
201
+ **Default:** Cookie is visible only to the domain or subdomain of the page where the cookie was created, except for Internet Explorer (see below).
202
+
203
+ **Examples:**
204
+
205
+ Assuming a cookie that is being created on `site.com`:
206
+
207
+ ```javascript
208
+ Cookies.set('name', 'value', { domain: 'subdomain.site.com' });
209
+ Cookies.get('name'); // => undefined (need to read at 'subdomain.site.com')
210
+ ```
211
+
212
+ **Note regarding Internet Explorer default behavior:**
213
+
214
+ > Q3: If I don’t specify a DOMAIN attribute (for) a cookie, IE sends it to all nested subdomains anyway?
215
+ > A: Yes, a cookie set on example.com will be sent to sub2.sub1.example.com.
216
+ > Internet Explorer differs from other browsers in this regard.
217
+
218
+ (From [Internet Explorer Cookie Internals (FAQ)](http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx))
219
+
220
+ This means that if you omit the `domain` attribute, it will be visible for a subdomain in IE.
221
+
222
+ ### secure
223
+
224
+ Either `true` or `false`, indicating if the cookie transmission requires a secure protocol (https).
225
+
226
+ **Default:** No secure protocol requirement.
227
+
228
+ **Examples:**
229
+
230
+ ```javascript
231
+ Cookies.set('name', 'value', { secure: true });
232
+ Cookies.get('name'); // => 'value'
233
+ Cookies.remove('name');
234
+ ```
235
+
236
+ ## Converters
237
+
238
+ ### Read
239
+
240
+ Create a new instance of the api that overrides the default decoding implementation.
241
+ All get methods that rely in a proper decoding to work, such as `Cookies.get()` and `Cookies.get('name')`, will run the converter first for each cookie.
242
+ The returning String will be used as the cookie value.
243
+
244
+ Example from reading one of the cookies that can only be decoded using the `escape` function:
245
+
246
+ ```javascript
247
+ document.cookie = 'escaped=%u5317';
248
+ document.cookie = 'default=%E5%8C%97';
249
+ var cookies = Cookies.withConverter(function (value, name) {
250
+ if ( name === 'escaped' ) {
251
+ return unescape(value);
252
+ }
253
+ });
254
+ cookies.get('escaped'); // 北
255
+ cookies.get('default'); // 北
256
+ cookies.get(); // { escaped: '北', default: '北' }
257
+ ```
258
+
259
+ ### Write
260
+
261
+ Create a new instance of the api that overrides the default encoding implementation:
262
+
263
+ ```javascript
264
+ Cookies.withConverter({
265
+ read: function (value, name) {
266
+ // Read converter
267
+ },
268
+ write: function (value, name) {
269
+ // Write converter
270
+ }
271
+ });
272
+ ```
273
+
274
+ ## Server-side integration
275
+
276
+ Check out the [Servers Docs](SERVER_SIDE.md)
277
+
278
+ ## Contributing
279
+
280
+ Check out the [Contributing Guidelines](CONTRIBUTING.md)
281
+
282
+ ## Security
283
+
284
+ For vulnerability reports, send an e-mail to `jscookieproject at gmail dot com`
285
+
286
+ ## Manual release steps
287
+
288
+ * Increment the "version" attribute of `package.json`
289
+ * Increment the version number in the `src/js.cookie.js` file
290
+ * If `major` bump, update jsDelivr CDN major version link on README
291
+ * Commit with the message "Release version x.x.x"
292
+ * Create version tag in git
293
+ * Create a github release and upload the minified file
294
+ * Change the `latest` tag pointer to the latest commit
295
+ * `git tag -f latest`
296
+ * `git push <remote> :refs/tags/latest`
297
+ * `git push origin master --tags`
298
+ * Release on npm
299
+
300
+ ## Authors
301
+
302
+ * [Klaus Hartl](https://github.com/carhartl)
303
+ * [Fagner Brack](https://github.com/FagnerMartinsBrack)
304
+ * And awesome [contributors](https://github.com/js-cookie/js-cookie/graphs/contributors)
@@ -0,0 +1,107 @@
1
+ # Server-side integration
2
+
3
+ There are some servers that are not compliant with the [RFC 6265](http://tools.ietf.org/html/rfc6265). For those, some characters that are not encoded by JavaScript Cookie might be treated differently.
4
+
5
+ Here we document the most important server-side peculiarities and their workarounds. Feel free to send a [Pull Request](https://github.com/js-cookie/js-cookie/blob/master/CONTRIBUTING.md#pull-requests) if you see something that can be improved.
6
+
7
+ *Disclaimer: This documentation is entirely based on community provided information. The examples below should be used only as a reference.*
8
+
9
+ ## PHP
10
+
11
+ In PHP, `setcookie()` function encodes cookie values using `urlencode()` function, which applies `%`-encoding but also encodes spaces as `+` signs, [for historical reasons](http://php.net/manual/en/function.urlencode.php#function.urlencode). When cookies are read back via `$_COOKIE` or `filter_input(INPUT_COOKIE)`, they would go trough a decoding process which decodes `%`-encoded sequences and also converts `+` signs back to spaces. However, the plus (`+`) sign is valid cookie character by itself, which means that libraries that adhere to standards will interpret `+` signs differently to PHP.
12
+
13
+ This presents two types of problems:
14
+
15
+ 1. PHP writes a cookie via `setcookie()` and all spaces get converted to `+` signs. JavaScript Cookie read `+` signs and uses them literally, since it is a valid cookie character.
16
+ 2. JavaScript Cookie writes a cookie with a value that contains `+` signs and stores it as is, since it is a valid cookie character. PHP read a cookie and converts `+` signs to spaces.
17
+
18
+ To make both PHP and JavaScript Cookie play nicely together?
19
+
20
+ **In PHP**, use `setrawcookie()` instead of `setcookie()`:
21
+
22
+ ```php
23
+ setrawcookie($name, rawurlencode($value));
24
+ ```
25
+
26
+ **In JavaScript**, use a custom converter.
27
+
28
+ **Example**:
29
+
30
+ ```javascript
31
+ var PHPCookies = Cookies.withConverter({
32
+ write: function (value) {
33
+ // Encode all characters according to the "encodeURIComponent" spec
34
+ return encodeURIComponent(value)
35
+ // Revert the characters that are unnecessarly encoded but are
36
+ // allowed in a cookie value, except for the plus sign (%2B)
37
+ .replace(/%(23|24|26|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
38
+ },
39
+ read: function (value) {
40
+ return value
41
+ // Decode the plus sign to spaces first, otherwise "legit" encoded pluses
42
+ // will be replaced incorrectly
43
+ .replace(/\+/g, ' ')
44
+ // Decode all characters according to the "encodeURIComponent" spec
45
+ .replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
46
+ }
47
+ });
48
+ ```
49
+
50
+ Rack seems to have [a similar problem](https://github.com/js-cookie/js-cookie/issues/70#issuecomment-132503017).
51
+
52
+ ## Tomcat
53
+
54
+ ### Version >= 7.x
55
+
56
+ It seems that there is a situation where Tomcat does not [read the parens correctly](https://github.com/js-cookie/js-cookie/issues/92#issue-107743407). To fix this you need to write a custom write converter.
57
+
58
+ **Example**:
59
+
60
+ ```javascript
61
+ var TomcatCookies = Cookies.withConverter({
62
+ write: function (value) {
63
+ // Encode all characters according to the "encodeURIComponent" spec
64
+ return encodeURIComponent(value)
65
+ // Revert the characters that are unnecessarly encoded but are
66
+ // allowed in a cookie value
67
+ .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent)
68
+ // Encode the parens that are interpreted incorrectly by Tomcat
69
+ .replace(/[\(\)]/g, escape);
70
+ }
71
+ });
72
+ ```
73
+
74
+ ### Version >= 8.0.15
75
+
76
+ Since Tomcat 8.0.15, it is possible to configure RFC 6265 compliance by changing your `conf/context.xml` file and adding the new [CookieProcessor](https://tomcat.apache.org/tomcat-8.0-doc/config/cookie-processor.html) nested inside the Context element. It would be like this:
77
+
78
+ ```xml
79
+ <Context>
80
+ <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"/>
81
+ </context>
82
+ ```
83
+ And you're all done.
84
+
85
+ Alternatively, you can check the [Java Cookie](https://github.com/js-cookie/java-cookie) project, which integrates nicely with JavaScript Cookie.
86
+
87
+ ## JBoss 7.1.1
88
+
89
+ It seems that the servlet implementation of JBoss 7.1.1 [does not read some characters correctly](https://github.com/js-cookie/js-cookie/issues/70#issuecomment-148944674), even though they are allowed as per [RFC 6265](https://tools.ietf.org/html/rfc6265#section-4.1.1). To fix this you need to write a custom converter to send those characters correctly.
90
+
91
+ **Example**:
92
+
93
+ ```javascript
94
+ var JBossCookies = Cookies.withConverter({
95
+ write: function (value) {
96
+ // Encode all characters according to the "encodeURIComponent" spec
97
+ return encodeURIComponent(value)
98
+ // Revert the characters that are unnecessarly encoded but are
99
+ // allowed in a cookie value
100
+ .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent)
101
+ // Encode again the characters that are not allowed in JBoss 7.1.1, like "[" and "]":
102
+ .replace(/[\[\]]/g, encodeURIComponent);
103
+ }
104
+ });
105
+ ```
106
+
107
+ Alternatively, you can check the [Java Cookie](https://github.com/js-cookie/java-cookie) project, which integrates nicely with JavaScript Cookie.
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "js-cookie",
3
+ "version": "2.2.0",
4
+ "description": "A simple, lightweight JavaScript API for handling cookies",
5
+ "main": "src/js.cookie.js",
6
+ "directories": {
7
+ "test": "test"
8
+ },
9
+ "keywords": [
10
+ "jquery-plugin",
11
+ "cookie",
12
+ "cookies",
13
+ "browser",
14
+ "amd",
15
+ "commonjs",
16
+ "client",
17
+ "js-cookie",
18
+ "browserify"
19
+ ],
20
+ "scripts": {
21
+ "test": "grunt test"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git://github.com/js-cookie/js-cookie.git"
26
+ },
27
+ "files": [
28
+ "src/**/*.js",
29
+ "SERVER_SIDE.md",
30
+ "CONTRIBUTING.md"
31
+ ],
32
+ "author": "Klaus Hartl",
33
+ "license": "MIT",
34
+ "devDependencies": {
35
+ "grunt": "1.0.1",
36
+ "grunt-compare-size": "0.4.2",
37
+ "grunt-contrib-connect": "1.0.2",
38
+ "grunt-contrib-jshint": "1.1.0",
39
+ "grunt-contrib-nodeunit": "1.0.0",
40
+ "grunt-contrib-qunit": "2.0.0",
41
+ "grunt-contrib-uglify": "2.3.0",
42
+ "grunt-contrib-watch": "1.0.0",
43
+ "grunt-jscs": "3.0.1",
44
+ "grunt-saucelabs": "9.0.0",
45
+ "gzip-js": "0.3.2",
46
+ "qunitjs": "1.23.1",
47
+ "requirejs": "2.3.5"
48
+ }
49
+ }
@@ -0,0 +1,165 @@
1
+ /*!
2
+ * JavaScript Cookie v2.2.0
3
+ * https://github.com/js-cookie/js-cookie
4
+ *
5
+ * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
6
+ * Released under the MIT license
7
+ */
8
+ ;(function (factory) {
9
+ var registeredInModuleLoader = false;
10
+ if (typeof define === 'function' && define.amd) {
11
+ define(factory);
12
+ registeredInModuleLoader = true;
13
+ }
14
+ if (typeof exports === 'object') {
15
+ module.exports = factory();
16
+ registeredInModuleLoader = true;
17
+ }
18
+ if (!registeredInModuleLoader) {
19
+ var OldCookies = window.Cookies;
20
+ var api = window.Cookies = factory();
21
+ api.noConflict = function () {
22
+ window.Cookies = OldCookies;
23
+ return api;
24
+ };
25
+ }
26
+ }(function () {
27
+ function extend () {
28
+ var i = 0;
29
+ var result = {};
30
+ for (; i < arguments.length; i++) {
31
+ var attributes = arguments[ i ];
32
+ for (var key in attributes) {
33
+ result[key] = attributes[key];
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+
39
+ function init (converter) {
40
+ function api (key, value, attributes) {
41
+ var result;
42
+ if (typeof document === 'undefined') {
43
+ return;
44
+ }
45
+
46
+ // Write
47
+
48
+ if (arguments.length > 1) {
49
+ attributes = extend({
50
+ path: '/'
51
+ }, api.defaults, attributes);
52
+
53
+ if (typeof attributes.expires === 'number') {
54
+ var expires = new Date();
55
+ expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
56
+ attributes.expires = expires;
57
+ }
58
+
59
+ // We're using "expires" because "max-age" is not supported by IE
60
+ attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
61
+
62
+ try {
63
+ result = JSON.stringify(value);
64
+ if (/^[\{\[]/.test(result)) {
65
+ value = result;
66
+ }
67
+ } catch (e) {}
68
+
69
+ if (!converter.write) {
70
+ value = encodeURIComponent(String(value))
71
+ .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
72
+ } else {
73
+ value = converter.write(value, key);
74
+ }
75
+
76
+ key = encodeURIComponent(String(key));
77
+ key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
78
+ key = key.replace(/[\(\)]/g, escape);
79
+
80
+ var stringifiedAttributes = '';
81
+
82
+ for (var attributeName in attributes) {
83
+ if (!attributes[attributeName]) {
84
+ continue;
85
+ }
86
+ stringifiedAttributes += '; ' + attributeName;
87
+ if (attributes[attributeName] === true) {
88
+ continue;
89
+ }
90
+ stringifiedAttributes += '=' + attributes[attributeName];
91
+ }
92
+ return (document.cookie = key + '=' + value + stringifiedAttributes);
93
+ }
94
+
95
+ // Read
96
+
97
+ if (!key) {
98
+ result = {};
99
+ }
100
+
101
+ // To prevent the for loop in the first place assign an empty array
102
+ // in case there are no cookies at all. Also prevents odd result when
103
+ // calling "get()"
104
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
105
+ var rdecode = /(%[0-9A-Z]{2})+/g;
106
+ var i = 0;
107
+
108
+ for (; i < cookies.length; i++) {
109
+ var parts = cookies[i].split('=');
110
+ var cookie = parts.slice(1).join('=');
111
+
112
+ if (!this.json && cookie.charAt(0) === '"') {
113
+ cookie = cookie.slice(1, -1);
114
+ }
115
+
116
+ try {
117
+ var name = parts[0].replace(rdecode, decodeURIComponent);
118
+ cookie = converter.read ?
119
+ converter.read(cookie, name) : converter(cookie, name) ||
120
+ cookie.replace(rdecode, decodeURIComponent);
121
+
122
+ if (this.json) {
123
+ try {
124
+ cookie = JSON.parse(cookie);
125
+ } catch (e) {}
126
+ }
127
+
128
+ if (key === name) {
129
+ result = cookie;
130
+ break;
131
+ }
132
+
133
+ if (!key) {
134
+ result[name] = cookie;
135
+ }
136
+ } catch (e) {}
137
+ }
138
+
139
+ return result;
140
+ }
141
+
142
+ api.set = api;
143
+ api.get = function (key) {
144
+ return api.call(api, key);
145
+ };
146
+ api.getJSON = function () {
147
+ return api.apply({
148
+ json: true
149
+ }, [].slice.call(arguments));
150
+ };
151
+ api.defaults = {};
152
+
153
+ api.remove = function (key, attributes) {
154
+ api(key, '', extend(attributes, {
155
+ expires: -1
156
+ }));
157
+ };
158
+
159
+ api.withConverter = init;
160
+
161
+ return api;
162
+ }
163
+
164
+ return init(function () {});
165
+ }));
@@ -0,0 +1,20 @@
1
+ //= require js-cookie/src/js.cookie
2
+
3
+ window.addEventListener('load', function() {
4
+ var gdprCookieConsent = document.querySelector('.js-gdpr__cookie_consent');
5
+
6
+ if(!gdprCookieConsent) return;
7
+ var COOKIE_KEY = 'gdpr.cookie_consent.ok'
8
+
9
+ var remove = function() {
10
+ if(gdprCookieConsent.parentNode) gdprCookieConsent.parentNode.removeChild(gdprCookieConsent);
11
+ }
12
+
13
+ if(Cookies.get(COOKIE_KEY) === 'true') remove()
14
+ else {
15
+ gdprCookieConsent.querySelector('.js-gdpr__cookie_consent__buttons__ok').addEventListener('click', function() {
16
+ Cookies.set(COOKIE_KEY, true, {path: '/', expires: 365});
17
+ remove()
18
+ });
19
+ }
20
+ });
@@ -0,0 +1,33 @@
1
+ .gdpr__cookie_consent
2
+ position: fixed
3
+ z-index: 999
4
+ right: 0
5
+ bottom: 0
6
+ left: 0
7
+ padding: 0 20px
8
+ text-align: center
9
+ border-top: 1px solid #ccc
10
+ background: #fff
11
+
12
+ @media only screen and (max-width : 480px)
13
+ font-size: 12px
14
+ position: initial
15
+
16
+ &__text
17
+ display: inline-block
18
+ padding: 20px 160px
19
+
20
+ @media only screen and (max-width : 480px)
21
+ padding: 20px 0
22
+
23
+ &__buttons
24
+ position: absolute
25
+ right: 10px
26
+ top: 12px
27
+
28
+ @media only screen and (max-width : 480px)
29
+ position: initial
30
+ margin-bottom: 10px
31
+
32
+ &__ok
33
+ padding: 15px 21px 15px !important
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-gdpr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Arnaud Levy
8
+ - Pierre-André Boissinot
9
+ - Julien Dargelos
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2018-07-02 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: middleman-core
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: middleman-sprockets
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: Adds a GDPR cookie consent and provides a simple checklist
58
+ email:
59
+ - alevy@lespoupees.paris
60
+ - paboissinot@lespoupees.paris
61
+ - contact@juliendargelos.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - lib/middleman-gdpr.rb
70
+ - lib/middleman-gdpr/extension.rb
71
+ - lib/middleman-gdpr/version.rb
72
+ - lib/middleman_extension.rb
73
+ - locales/de.yml
74
+ - locales/en.yml
75
+ - locales/es.yml
76
+ - locales/fr.yml
77
+ - locales/it.yml
78
+ - locales/zh.yml
79
+ - node_modules/js-cookie/CONTRIBUTING.md
80
+ - node_modules/js-cookie/LICENSE
81
+ - node_modules/js-cookie/README.md
82
+ - node_modules/js-cookie/SERVER_SIDE.md
83
+ - node_modules/js-cookie/package.json
84
+ - node_modules/js-cookie/src/js.cookie.js
85
+ - source/javascripts/gdpr/cookie_consent.js
86
+ - source/stylesheets/gdpr/cookie_consent.sass
87
+ homepage: https://github.com/lespoupeesrusses/middleman-gdpr
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.7.6
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Helps getting your Middleman website GDPR compliant
111
+ test_files: []