Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

util.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. 'use strict';
  2. module.exports = {
  3. copy: copy,
  4. checkDataType: checkDataType,
  5. checkDataTypes: checkDataTypes,
  6. coerceToTypes: coerceToTypes,
  7. toHash: toHash,
  8. getProperty: getProperty,
  9. escapeQuotes: escapeQuotes,
  10. equal: require('fast-deep-equal'),
  11. ucs2length: require('./ucs2length'),
  12. varOccurences: varOccurences,
  13. varReplace: varReplace,
  14. schemaHasRules: schemaHasRules,
  15. schemaHasRulesExcept: schemaHasRulesExcept,
  16. schemaUnknownRules: schemaUnknownRules,
  17. toQuotedString: toQuotedString,
  18. getPathExpr: getPathExpr,
  19. getPath: getPath,
  20. getData: getData,
  21. unescapeFragment: unescapeFragment,
  22. unescapeJsonPointer: unescapeJsonPointer,
  23. escapeFragment: escapeFragment,
  24. escapeJsonPointer: escapeJsonPointer
  25. };
  26. function copy(o, to) {
  27. to = to || {};
  28. for (var key in o) to[key] = o[key];
  29. return to;
  30. }
  31. function checkDataType(dataType, data, strictNumbers, negate) {
  32. var EQUAL = negate ? ' !== ' : ' === '
  33. , AND = negate ? ' || ' : ' && '
  34. , OK = negate ? '!' : ''
  35. , NOT = negate ? '' : '!';
  36. switch (dataType) {
  37. case 'null': return data + EQUAL + 'null';
  38. case 'array': return OK + 'Array.isArray(' + data + ')';
  39. case 'object': return '(' + OK + data + AND +
  40. 'typeof ' + data + EQUAL + '"object"' + AND +
  41. NOT + 'Array.isArray(' + data + '))';
  42. case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +
  43. NOT + '(' + data + ' % 1)' +
  44. AND + data + EQUAL + data +
  45. (strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')';
  46. case 'number': return '(typeof ' + data + EQUAL + '"' + dataType + '"' +
  47. (strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')';
  48. default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';
  49. }
  50. }
  51. function checkDataTypes(dataTypes, data, strictNumbers) {
  52. switch (dataTypes.length) {
  53. case 1: return checkDataType(dataTypes[0], data, strictNumbers, true);
  54. default:
  55. var code = '';
  56. var types = toHash(dataTypes);
  57. if (types.array && types.object) {
  58. code = types.null ? '(': '(!' + data + ' || ';
  59. code += 'typeof ' + data + ' !== "object")';
  60. delete types.null;
  61. delete types.array;
  62. delete types.object;
  63. }
  64. if (types.number) delete types.integer;
  65. for (var t in types)
  66. code += (code ? ' && ' : '' ) + checkDataType(t, data, strictNumbers, true);
  67. return code;
  68. }
  69. }
  70. var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);
  71. function coerceToTypes(optionCoerceTypes, dataTypes) {
  72. if (Array.isArray(dataTypes)) {
  73. var types = [];
  74. for (var i=0; i<dataTypes.length; i++) {
  75. var t = dataTypes[i];
  76. if (COERCE_TO_TYPES[t]) types[types.length] = t;
  77. else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;
  78. }
  79. if (types.length) return types;
  80. } else if (COERCE_TO_TYPES[dataTypes]) {
  81. return [dataTypes];
  82. } else if (optionCoerceTypes === 'array' && dataTypes === 'array') {
  83. return ['array'];
  84. }
  85. }
  86. function toHash(arr) {
  87. var hash = {};
  88. for (var i=0; i<arr.length; i++) hash[arr[i]] = true;
  89. return hash;
  90. }
  91. var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
  92. var SINGLE_QUOTE = /'|\\/g;
  93. function getProperty(key) {
  94. return typeof key == 'number'
  95. ? '[' + key + ']'
  96. : IDENTIFIER.test(key)
  97. ? '.' + key
  98. : "['" + escapeQuotes(key) + "']";
  99. }
  100. function escapeQuotes(str) {
  101. return str.replace(SINGLE_QUOTE, '\\$&')
  102. .replace(/\n/g, '\\n')
  103. .replace(/\r/g, '\\r')
  104. .replace(/\f/g, '\\f')
  105. .replace(/\t/g, '\\t');
  106. }
  107. function varOccurences(str, dataVar) {
  108. dataVar += '[^0-9]';
  109. var matches = str.match(new RegExp(dataVar, 'g'));
  110. return matches ? matches.length : 0;
  111. }
  112. function varReplace(str, dataVar, expr) {
  113. dataVar += '([^0-9])';
  114. expr = expr.replace(/\$/g, '$$$$');
  115. return str.replace(new RegExp(dataVar, 'g'), expr + '$1');
  116. }
  117. function schemaHasRules(schema, rules) {
  118. if (typeof schema == 'boolean') return !schema;
  119. for (var key in schema) if (rules[key]) return true;
  120. }
  121. function schemaHasRulesExcept(schema, rules, exceptKeyword) {
  122. if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';
  123. for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
  124. }
  125. function schemaUnknownRules(schema, rules) {
  126. if (typeof schema == 'boolean') return;
  127. for (var key in schema) if (!rules[key]) return key;
  128. }
  129. function toQuotedString(str) {
  130. return '\'' + escapeQuotes(str) + '\'';
  131. }
  132. function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
  133. var path = jsonPointers // false by default
  134. ? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')
  135. : (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');
  136. return joinPaths(currentPath, path);
  137. }
  138. function getPath(currentPath, prop, jsonPointers) {
  139. var path = jsonPointers // false by default
  140. ? toQuotedString('/' + escapeJsonPointer(prop))
  141. : toQuotedString(getProperty(prop));
  142. return joinPaths(currentPath, path);
  143. }
  144. var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
  145. var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
  146. function getData($data, lvl, paths) {
  147. var up, jsonPointer, data, matches;
  148. if ($data === '') return 'rootData';
  149. if ($data[0] == '/') {
  150. if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);
  151. jsonPointer = $data;
  152. data = 'rootData';
  153. } else {
  154. matches = $data.match(RELATIVE_JSON_POINTER);
  155. if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);
  156. up = +matches[1];
  157. jsonPointer = matches[2];
  158. if (jsonPointer == '#') {
  159. if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);
  160. return paths[lvl - up];
  161. }
  162. if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);
  163. data = 'data' + ((lvl - up) || '');
  164. if (!jsonPointer) return data;
  165. }
  166. var expr = data;
  167. var segments = jsonPointer.split('/');
  168. for (var i=0; i<segments.length; i++) {
  169. var segment = segments[i];
  170. if (segment) {
  171. data += getProperty(unescapeJsonPointer(segment));
  172. expr += ' && ' + data;
  173. }
  174. }
  175. return expr;
  176. }
  177. function joinPaths (a, b) {
  178. if (a == '""') return b;
  179. return (a + ' + ' + b).replace(/([^\\])' \+ '/g, '$1');
  180. }
  181. function unescapeFragment(str) {
  182. return unescapeJsonPointer(decodeURIComponent(str));
  183. }
  184. function escapeFragment(str) {
  185. return encodeURIComponent(escapeJsonPointer(str));
  186. }
  187. function escapeJsonPointer(str) {
  188. return str.replace(/~/g, '~0').replace(/\//g, '~1');
  189. }
  190. function unescapeJsonPointer(str) {
  191. return str.replace(/~1/g, '/').replace(/~0/g, '~');
  192. }