Skip to content

Commit

Permalink
Issue #2550717 by mradcliffe, bnjmnm, finnsky, Manuel Garcia, lauriii…
Browse files Browse the repository at this point in the history
…, longwave, tedbow, silesky, catch, xjm, droplet, johndevman, nod_, marassa: [JS] Replace jQuery.cookie with JS-cookie and provide a BC layer
  • Loading branch information
lauriii committed Mar 18, 2020
1 parent 424781f commit e1c195f
Show file tree
Hide file tree
Showing 16 changed files with 768 additions and 12 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_modules/**/*
!*.es6.js
modules/locale/tests/locale_test.es6.js
!tests/Drupal/Nightwatch/**/*.js
misc/polyfills/object.assign.es6.js
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"jQuery": true,
"_": true,
"matchMedia": true,
"Cookies": true,
"Backbone": true,
"Modernizr": true,
"Popper": true,
Expand Down
2 changes: 0 additions & 2 deletions assets/vendor/jquery.cookie/jquery.cookie.min.js

This file was deleted.

3 changes: 3 additions & 0 deletions assets/vendor/js-cookie/js.cookie.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 21 additions & 10 deletions core.libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ drupal.form:
- core/jquery
- core/drupal
- core/drupal.debounce
- core/jquery.cookie
- core/jquery.once

drupal.machine-name:
Expand All @@ -251,6 +250,11 @@ drupal.message:
- core/drupal
- core/drupal.announce

drupal.object.assign:
version: VERSION
js:
misc/polyfills/object.assign.js: { weight: -20 }

drupal.progress:
version: VERSION
js:
Expand Down Expand Up @@ -289,7 +293,6 @@ drupal.tabledrag:
- core/drupal
- core/drupalSettings
- core/jquery.once
- core/jquery.cookie

drupal.tableheader:
version: VERSION
Expand Down Expand Up @@ -370,16 +373,13 @@ jquery:
assets/vendor/jquery/jquery.min.js: { minified: true, weight: -20 }

jquery.cookie:
remote: https://github.com/carhartl/jquery-cookie
version: "v1.4.1"
license:
name: MIT
url: https://github.com/carhartl/jquery-cookie/blob/v1.4.1/MIT-LICENSE.txt
gpl-compatible: true
version: VERSION
js:
assets/vendor/jquery.cookie/jquery.cookie.min.js: { minified: true }
misc/jquery.cookie.shim.js: {}
dependencies:
- core/jquery
- core/drupal
- core/js-cookie

jquery.farbtastic:
remote: https://github.com/mattfarina/farbtastic
Expand Down Expand Up @@ -425,7 +425,6 @@ jquery.joyride:
assets/vendor/jquery-joyride/jquery.joyride-2.1.js: { }
dependencies:
- core/jquery
- core/jquery.cookie

jquery.once:
remote: https://github.com/RobLoach/jquery-once
Expand Down Expand Up @@ -1024,3 +1023,15 @@ drupal.dialog.off_canvas:
- core/drupal.announce
- core/drupal.dialog
- core/drupal.dialog.ajax

js-cookie:
remote: https://github.com/js-cookie/js-cookie
version: "v2.2.1"
license:
name: MIT
url: https://github.com/js-cookie/js-cookie/blob/v2.2.1/MIT-LICENSE.txt
gpl-compatible: true
js:
assets/vendor/js-cookie/js.cookie.min.js: {}
dependencies:
- core/drupal.object.assign
193 changes: 193 additions & 0 deletions misc/jquery.cookie.shim.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/**
* @file
* Defines a backwards-compatible shim for jquery.cookie.
*/

/**
* The core/js-cookie library object.
*
* @global
*
* @var {object} Cookies
*/

(($, Drupal, cookies) => {
/**
* Determines if an object is a function.
*
* @param {Object} obj
* The object to check.
*
* @return {boolean}
* True if the object is a function.
*/
const isFunction = obj =>
Object.prototype.toString.call(obj) === '[object Function]';

/**
* Decodes cookie value for compatibility with jquery.cookie.
*
* @param {string} value
* The cookie value to parse.
*
* @return {string}
* The cookie value for the reader to return.
*/
const parseCookieValue = value => {
if (value.indexOf('"') === 0) {
value = value
.slice(1, -1)
.replace(/\\"/g, '"')
.replace(/\\\\/g, '\\');
}
return decodeURIComponent(value.replace(/\+/g, ' '));
};

/**
* Wraps the cookie value to support unsanitized values.
*
* Decoding strings is the job of the converter when using js-cookie, and
* the shim uses the same decode function as that library when the deprecated
* raw option is not used.
*
* @param {string} cookieValue
* The cookie value.
* @param {string} cookieName
* The cookie name.
* @param {reader~converterCallback} converter
* A function that takes the cookie value for further processing.
* @param {boolean} readUnsanitized
* Uses the unsanitized value when set to true.
*
* @return {string}
* The cookie value that js-cookie will return.
*/
const reader = (cookieValue, cookieName, converter, readUnsanitized) => {
const value = readUnsanitized ? cookieValue : parseCookieValue(cookieValue);

if (converter !== undefined && isFunction(converter)) {
return converter(value, cookieName);
}
return value;
};

/**
* Gets or sets a browser cookie.
*
* @example
* // Returns 'myCookie=myCookieValue'.
* $.cookie('myCookie', 'myCookieValue');
* @example
* // Returns 'myCookieValue'.
* $.cookie('myCookie');
*
* @example
* // Returns the literal URI-encoded value of {"key": "value"} as the cookie
* // value along with the path as in the above example.
* $.cookie('myCookie', { key: 'value' });
* @example
* $.cookie.json = true;
* // Returns { key: 'value' }.
* $.cookie('myCookie');
*
* @param {string} key
* The name of the cookie.
* @param {string|Object|Function|undefined} value
* A js-cookie converter callback when used as a getter. This callback must
* be a function when using this shim for backwards-compatiblity with
* jquery.cookie. When used as a setter, value is the string or JSON object
* to be used as the cookie value.
* @param {Object|undefined} options
* Overrides the default options when used as a setter. See the js-cookie
* library README.md file for details.
*
* @return {string}
* Returns the cookie name, value, and other properties based on the
* return value of the document.cookie setter.
*
* @see https://www.drupal.org/node/3104677
* @see https://github.com/js-cookie/js-cookie/blob/v2.2.1/README.md
*/
$.cookie = (key, value = undefined, options = undefined) => {
if (value !== undefined && !isFunction(value)) {
// The caller is setting a cookie value and not trying to retrieve the
// cookie value using a converter callback.
const attributes = Object.assign($.cookie.defaults, options);

if (!$.cookie.json) {
// An object that is passed in must be typecast to a string when the
// "json" option is not set because js-cookie will always stringify
// JSON cookie values.
value = String(value);
}

// If the expires value is a non-empty string, it needs to be converted
// to a Date() object before being sent to js-cookie.
if (typeof attributes.expires === 'string' && attributes.expires !== '') {
attributes.expires = new Date(attributes.expires);
}

const cookieSetter = cookies.withConverter({
write: cookieValue => encodeURIComponent(cookieValue),
});

return cookieSetter.set(key, value, attributes);
}

// Use either js-cookie or pass in a converter to get the raw cookie value,
// which has security implications, but remains in place for
// backwards-compatibility.
const userProvidedConverter = value;
const cookiesShim = cookies.withConverter((cookieValue, cookieName) =>
reader(cookieValue, cookieName, userProvidedConverter, $.cookie.raw),
);

return $.cookie.json === true
? cookiesShim.getJSON(key)
: cookiesShim.get(key);
};

/**
* @prop {Object} defaults
* The default options when setting a cookie.
* @prop {string} defaults.path
* The default path for the cookie is ''.
* @prop {undefined} defaults.expires
* There is no default value for the expires option. The default expiration
* is set to an empty string.
*/
$.cookie.defaults = Object.assign({ path: '' }, cookies.defaults);

/**
* @prop {boolean} json
* True if the cookie value should be parsed as JSON.
*/
$.cookie.json = false;

/**
* @prop {boolean} json
* True if the cookie value should be returned as-is without decoding
* URI entities. In jquery.cookie, this also would not encode the cookie
* name, but js-cookie does not allow this.
*/
$.cookie.raw = false;

/**
* Removes a browser cookie.
*
* @param {string} key
* The name of the cookie.
* @param {Object} options
* Optional options. See the js-cookie library README.md for more details.
*
* @return {boolean}
* Returns true when the cookie is successfully removed.
*
* @see https://www.drupal.org/node/3104677
* @see https://github.com/js-cookie/js-cookie/blob/v2.2.1/README.md
*/
$.removeCookie = (key, options) => {
cookies.remove(key, Object.assign($.cookie.defaults, options));
return !cookies.get(key);
};
})(jQuery, Drupal, window.Cookies);
71 changes: 71 additions & 0 deletions misc/jquery.cookie.shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/

(function ($, Drupal, cookies) {
var isFunction = function isFunction(obj) {
return Object.prototype.toString.call(obj) === '[object Function]';
};

var parseCookieValue = function parseCookieValue(value) {
if (value.indexOf('"') === 0) {
value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
return decodeURIComponent(value.replace(/\+/g, ' '));
};

var reader = function reader(cookieValue, cookieName, converter, readUnsanitized) {
var value = readUnsanitized ? cookieValue : parseCookieValue(cookieValue);

if (converter !== undefined && isFunction(converter)) {
return converter(value, cookieName);
}
return value;
};

$.cookie = function (key) {
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;

if (value !== undefined && !isFunction(value)) {
var attributes = Object.assign($.cookie.defaults, options);

if (!$.cookie.json) {
value = String(value);
}

if (typeof attributes.expires === 'string' && attributes.expires !== '') {
attributes.expires = new Date(attributes.expires);
}

var cookieSetter = cookies.withConverter({
write: function write(cookieValue) {
return encodeURIComponent(cookieValue);
}
});

return cookieSetter.set(key, value, attributes);
}

var userProvidedConverter = value;
var cookiesShim = cookies.withConverter(function (cookieValue, cookieName) {
return reader(cookieValue, cookieName, userProvidedConverter, $.cookie.raw);
});

return $.cookie.json === true ? cookiesShim.getJSON(key) : cookiesShim.get(key);
};

$.cookie.defaults = Object.assign({ path: '' }, cookies.defaults);

$.cookie.json = false;

$.cookie.raw = false;

$.removeCookie = function (key, options) {
cookies.remove(key, Object.assign($.cookie.defaults, options));
return !cookies.get(key);
};
})(jQuery, Drupal, window.Cookies);

0 comments on commit e1c195f

Please sign in to comment.