utils.mjs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import { RFC1738 } from "./formats.mjs";
  2. const has = Object.prototype.hasOwnProperty;
  3. const is_array = Array.isArray;
  4. const hex_table = (() => {
  5. const array = [];
  6. for (let i = 0; i < 256; ++i) {
  7. array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
  8. }
  9. return array;
  10. })();
  11. function compact_queue(queue) {
  12. while (queue.length > 1) {
  13. const item = queue.pop();
  14. if (!item)
  15. continue;
  16. const obj = item.obj[item.prop];
  17. if (is_array(obj)) {
  18. const compacted = [];
  19. for (let j = 0; j < obj.length; ++j) {
  20. if (typeof obj[j] !== 'undefined') {
  21. compacted.push(obj[j]);
  22. }
  23. }
  24. // @ts-ignore
  25. item.obj[item.prop] = compacted;
  26. }
  27. }
  28. }
  29. function array_to_object(source, options) {
  30. const obj = options && options.plainObjects ? Object.create(null) : {};
  31. for (let i = 0; i < source.length; ++i) {
  32. if (typeof source[i] !== 'undefined') {
  33. obj[i] = source[i];
  34. }
  35. }
  36. return obj;
  37. }
  38. export function merge(target, source, options = {}) {
  39. if (!source) {
  40. return target;
  41. }
  42. if (typeof source !== 'object') {
  43. if (is_array(target)) {
  44. target.push(source);
  45. }
  46. else if (target && typeof target === 'object') {
  47. if ((options && (options.plainObjects || options.allowPrototypes)) ||
  48. !has.call(Object.prototype, source)) {
  49. target[source] = true;
  50. }
  51. }
  52. else {
  53. return [target, source];
  54. }
  55. return target;
  56. }
  57. if (!target || typeof target !== 'object') {
  58. return [target].concat(source);
  59. }
  60. let mergeTarget = target;
  61. if (is_array(target) && !is_array(source)) {
  62. // @ts-ignore
  63. mergeTarget = array_to_object(target, options);
  64. }
  65. if (is_array(target) && is_array(source)) {
  66. source.forEach(function (item, i) {
  67. if (has.call(target, i)) {
  68. const targetItem = target[i];
  69. if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
  70. target[i] = merge(targetItem, item, options);
  71. }
  72. else {
  73. target.push(item);
  74. }
  75. }
  76. else {
  77. target[i] = item;
  78. }
  79. });
  80. return target;
  81. }
  82. return Object.keys(source).reduce(function (acc, key) {
  83. const value = source[key];
  84. if (has.call(acc, key)) {
  85. acc[key] = merge(acc[key], value, options);
  86. }
  87. else {
  88. acc[key] = value;
  89. }
  90. return acc;
  91. }, mergeTarget);
  92. }
  93. export function assign_single_source(target, source) {
  94. return Object.keys(source).reduce(function (acc, key) {
  95. acc[key] = source[key];
  96. return acc;
  97. }, target);
  98. }
  99. export function decode(str, _, charset) {
  100. const strWithoutPlus = str.replace(/\+/g, ' ');
  101. if (charset === 'iso-8859-1') {
  102. // unescape never throws, no try...catch needed:
  103. return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
  104. }
  105. // utf-8
  106. try {
  107. return decodeURIComponent(strWithoutPlus);
  108. }
  109. catch (e) {
  110. return strWithoutPlus;
  111. }
  112. }
  113. const limit = 1024;
  114. export const encode = (str, _defaultEncoder, charset, _kind, format) => {
  115. // This code was originally written by Brian White for the io.js core querystring library.
  116. // It has been adapted here for stricter adherence to RFC 3986
  117. if (str.length === 0) {
  118. return str;
  119. }
  120. let string = str;
  121. if (typeof str === 'symbol') {
  122. string = Symbol.prototype.toString.call(str);
  123. }
  124. else if (typeof str !== 'string') {
  125. string = String(str);
  126. }
  127. if (charset === 'iso-8859-1') {
  128. return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
  129. return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
  130. });
  131. }
  132. let out = '';
  133. for (let j = 0; j < string.length; j += limit) {
  134. const segment = string.length >= limit ? string.slice(j, j + limit) : string;
  135. const arr = [];
  136. for (let i = 0; i < segment.length; ++i) {
  137. let c = segment.charCodeAt(i);
  138. if (c === 0x2d || // -
  139. c === 0x2e || // .
  140. c === 0x5f || // _
  141. c === 0x7e || // ~
  142. (c >= 0x30 && c <= 0x39) || // 0-9
  143. (c >= 0x41 && c <= 0x5a) || // a-z
  144. (c >= 0x61 && c <= 0x7a) || // A-Z
  145. (format === RFC1738 && (c === 0x28 || c === 0x29)) // ( )
  146. ) {
  147. arr[arr.length] = segment.charAt(i);
  148. continue;
  149. }
  150. if (c < 0x80) {
  151. arr[arr.length] = hex_table[c];
  152. continue;
  153. }
  154. if (c < 0x800) {
  155. arr[arr.length] = hex_table[0xc0 | (c >> 6)] + hex_table[0x80 | (c & 0x3f)];
  156. continue;
  157. }
  158. if (c < 0xd800 || c >= 0xe000) {
  159. arr[arr.length] =
  160. hex_table[0xe0 | (c >> 12)] + hex_table[0x80 | ((c >> 6) & 0x3f)] + hex_table[0x80 | (c & 0x3f)];
  161. continue;
  162. }
  163. i += 1;
  164. c = 0x10000 + (((c & 0x3ff) << 10) | (segment.charCodeAt(i) & 0x3ff));
  165. arr[arr.length] =
  166. hex_table[0xf0 | (c >> 18)] +
  167. hex_table[0x80 | ((c >> 12) & 0x3f)] +
  168. hex_table[0x80 | ((c >> 6) & 0x3f)] +
  169. hex_table[0x80 | (c & 0x3f)];
  170. }
  171. out += arr.join('');
  172. }
  173. return out;
  174. };
  175. export function compact(value) {
  176. const queue = [{ obj: { o: value }, prop: 'o' }];
  177. const refs = [];
  178. for (let i = 0; i < queue.length; ++i) {
  179. const item = queue[i];
  180. // @ts-ignore
  181. const obj = item.obj[item.prop];
  182. const keys = Object.keys(obj);
  183. for (let j = 0; j < keys.length; ++j) {
  184. const key = keys[j];
  185. const val = obj[key];
  186. if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
  187. queue.push({ obj: obj, prop: key });
  188. refs.push(val);
  189. }
  190. }
  191. }
  192. compact_queue(queue);
  193. return value;
  194. }
  195. export function is_regexp(obj) {
  196. return Object.prototype.toString.call(obj) === '[object RegExp]';
  197. }
  198. export function is_buffer(obj) {
  199. if (!obj || typeof obj !== 'object') {
  200. return false;
  201. }
  202. return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
  203. }
  204. export function combine(a, b) {
  205. return [].concat(a, b);
  206. }
  207. export function maybe_map(val, fn) {
  208. if (is_array(val)) {
  209. const mapped = [];
  210. for (let i = 0; i < val.length; i += 1) {
  211. mapped.push(fn(val[i]));
  212. }
  213. return mapped;
  214. }
  215. return fn(val);
  216. }
  217. //# sourceMappingURL=utils.mjs.map