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