jquery.cookie.shim.es6.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * @file
  3. * Defines a backwards-compatible shim for jquery.cookie.
  4. */
  5. /**
  6. * The core/js-cookie library object.
  7. *
  8. * @global
  9. *
  10. * @var {object} Cookies
  11. */
  12. (($, Drupal, cookies) => {
  13. /**
  14. * Determines if an object is a function.
  15. *
  16. * @param {Object} obj
  17. * The object to check.
  18. *
  19. * @return {boolean}
  20. * True if the object is a function.
  21. */
  22. const isFunction = obj =>
  23. Object.prototype.toString.call(obj) === '[object Function]';
  24. /**
  25. * Decodes cookie value for compatibility with jquery.cookie.
  26. *
  27. * @param {string} value
  28. * The cookie value to parse.
  29. * @param {boolean} parseJson
  30. * Whether cookie value should be parsed from JSON.
  31. *
  32. * @return {string}
  33. * The cookie value for the reader to return.
  34. */
  35. const parseCookieValue = (value, parseJson) => {
  36. if (value.indexOf('"') === 0) {
  37. value = value
  38. .slice(1, -1)
  39. .replace(/\\"/g, '"')
  40. .replace(/\\\\/g, '\\');
  41. }
  42. try {
  43. value = decodeURIComponent(value.replace(/\+/g, ' '));
  44. return parseJson ? JSON.parse(value) : value;
  45. } catch (e) {
  46. // Exceptions on JSON parsing should be ignored.
  47. }
  48. };
  49. /**
  50. * Wraps the cookie value to support unsanitized values.
  51. *
  52. * Decoding strings is the job of the converter when using js-cookie, and
  53. * the shim uses the same decode function as that library when the deprecated
  54. * raw option is not used.
  55. *
  56. * @param {string} cookieValue
  57. * The cookie value.
  58. * @param {string} cookieName
  59. * The cookie name.
  60. * @param {reader~converterCallback} converter
  61. * A function that takes the cookie value for further processing.
  62. * @param {boolean} readUnsanitized
  63. * Uses the unsanitized value when set to true.
  64. * @param {boolean} parseJson
  65. * Whether cookie value should be parsed from JSON.
  66. *
  67. * @return {string}
  68. * The cookie value that js-cookie will return.
  69. */
  70. const reader = (
  71. cookieValue,
  72. cookieName,
  73. converter,
  74. readUnsanitized,
  75. parseJson,
  76. ) => {
  77. const value = readUnsanitized
  78. ? cookieValue
  79. : parseCookieValue(cookieValue, parseJson);
  80. if (converter !== undefined && isFunction(converter)) {
  81. return converter(value, cookieName);
  82. }
  83. return value;
  84. };
  85. /**
  86. * Gets or sets a browser cookie.
  87. *
  88. * @example
  89. * // Returns 'myCookie=myCookieValue'.
  90. * $.cookie('myCookie', 'myCookieValue');
  91. * @example
  92. * // Returns 'myCookieValue'.
  93. * $.cookie('myCookie');
  94. *
  95. * @example
  96. * // Returns the literal URI-encoded value of {"key": "value"} as the cookie
  97. * // value along with the path as in the above example.
  98. * $.cookie('myCookie', { key: 'value' });
  99. * @example
  100. * $.cookie.json = true;
  101. * // Returns { key: 'value' }.
  102. * $.cookie('myCookie');
  103. *
  104. * @param {string} key
  105. * The name of the cookie.
  106. * @param {string|Object|Function|undefined} value
  107. * A js-cookie converter callback when used as a getter. This callback must
  108. * be a function when using this shim for backwards-compatibility with
  109. * jquery.cookie. When used as a setter, value is the string or JSON object
  110. * to be used as the cookie value.
  111. * @param {Object|undefined} options
  112. * Overrides the default options when used as a setter. See the js-cookie
  113. * library README.md file for details.
  114. *
  115. * @return {string}
  116. * Returns the cookie name, value, and other properties based on the
  117. * return value of the document.cookie setter.
  118. *
  119. * @see https://www.drupal.org/node/3104677
  120. * @see https://github.com/js-cookie/js-cookie/blob/v3.0.0-rc.0/README.md
  121. */
  122. $.cookie = (key, value = undefined, options = undefined) => {
  123. // Key should be only encoded if it exists and when not in a raw mode.
  124. key = key && !$.cookie.raw ? encodeURIComponent(key) : key;
  125. if (value !== undefined && !isFunction(value)) {
  126. // The caller is setting a cookie value and not trying to retrieve the
  127. // cookie value using a converter callback.
  128. const attributes = Object.assign({}, $.cookie.defaults, options);
  129. if (typeof attributes.expires === 'string' && attributes.expires !== '') {
  130. attributes.expires = new Date(attributes.expires);
  131. }
  132. const cookieSetter = cookies.withConverter({
  133. write: cookieValue => encodeURIComponent(cookieValue),
  134. });
  135. value =
  136. $.cookie.json && !$.cookie.raw ? JSON.stringify(value) : String(value);
  137. return cookieSetter.set(key, value, attributes);
  138. }
  139. // Use either js-cookie or pass in a converter to get the raw cookie value,
  140. // which has security implications, but remains in place for
  141. // backwards-compatibility.
  142. const userProvidedConverter = value;
  143. const cookiesShim = cookies.withConverter({
  144. read: (cookieValue, cookieName) =>
  145. reader(
  146. cookieValue,
  147. cookieName,
  148. userProvidedConverter,
  149. $.cookie.raw,
  150. $.cookie.json,
  151. ),
  152. });
  153. if (key !== undefined) {
  154. return cookiesShim.get(key);
  155. }
  156. const results = cookiesShim.get();
  157. Object.keys(results).forEach(resultKey => {
  158. if (results[resultKey] === undefined) {
  159. delete results[resultKey];
  160. }
  161. });
  162. return results;
  163. };
  164. /**
  165. * @prop {Object} defaults
  166. * The default options when setting a cookie.
  167. * @prop {string} defaults.path
  168. * The default path for the cookie is ''.
  169. * @prop {undefined} defaults.expires
  170. * There is no default value for the expires option. The default expiration
  171. * is set to an empty string.
  172. */
  173. $.cookie.defaults = Object.assign({ path: '' }, cookies.defaults);
  174. /**
  175. * @prop {boolean} json
  176. * True if the cookie value should be parsed as JSON.
  177. */
  178. $.cookie.json = false;
  179. /**
  180. * @prop {boolean} json
  181. * True if the cookie value should be returned as-is without decoding
  182. * URI entities. In jquery.cookie, this also would not encode the cookie
  183. * name, but js-cookie does not allow this.
  184. */
  185. $.cookie.raw = false;
  186. /**
  187. * Removes a browser cookie.
  188. *
  189. * @param {string} key
  190. * The name of the cookie.
  191. * @param {Object} options
  192. * Optional options. See the js-cookie library README.md for more details.
  193. *
  194. * @return {boolean}
  195. * Returns true when the cookie is successfully removed.
  196. *
  197. * @see https://www.drupal.org/node/3104677
  198. * @see https://github.com/js-cookie/js-cookie/blob/v3.0.0-rc.0/README.md
  199. */
  200. $.removeCookie = (key, options) => {
  201. cookies.remove(key, Object.assign({}, $.cookie.defaults, options));
  202. return !cookies.get(key);
  203. };
  204. })(jQuery, Drupal, window.Cookies);