12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use strict';
  2. var traverse = module.exports = function (schema, opts, cb) {
  3. if (typeof opts == 'function') {
  4. cb = opts;
  5. opts = {};
  6. }
  7. _traverse(opts, cb, schema, '', schema);
  8. };
  9. traverse.keywords = {
  10. additionalItems: true,
  11. items: true,
  12. contains: true,
  13. additionalProperties: true,
  14. propertyNames: true,
  15. not: true
  16. };
  17. traverse.arrayKeywords = {
  18. items: true,
  19. allOf: true,
  20. anyOf: true,
  21. oneOf: true
  22. };
  23. traverse.propsKeywords = {
  24. definitions: true,
  25. properties: true,
  26. patternProperties: true,
  27. dependencies: true
  28. };
  29. traverse.skipKeywords = {
  30. enum: true,
  31. const: true,
  32. required: true,
  33. maximum: true,
  34. minimum: true,
  35. exclusiveMaximum: true,
  36. exclusiveMinimum: true,
  37. multipleOf: true,
  38. maxLength: true,
  39. minLength: true,
  40. pattern: true,
  41. format: true,
  42. maxItems: true,
  43. minItems: true,
  44. uniqueItems: true,
  45. maxProperties: true,
  46. minProperties: true
  47. };
  48. function _traverse(opts, cb, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
  49. if (schema && typeof schema == 'object' && !Array.isArray(schema)) {
  50. cb(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
  51. for (var key in schema) {
  52. var sch = schema[key];
  53. if (Array.isArray(sch)) {
  54. if (key in traverse.arrayKeywords) {
  55. for (var i=0; i<sch.length; i++)
  56. _traverse(opts, cb, sch[i], jsonPtr + '/' + key + '/' + i, rootSchema, jsonPtr, key, schema, i);
  57. }
  58. } else if (key in traverse.propsKeywords) {
  59. if (sch && typeof sch == 'object') {
  60. for (var prop in sch)
  61. _traverse(opts, cb, sch[prop], jsonPtr + '/' + key + '/' + escapeJsonPtr(prop), rootSchema, jsonPtr, key, schema, prop);
  62. }
  63. } else if (key in traverse.keywords || (opts.allKeys && !(key in traverse.skipKeywords))) {
  64. _traverse(opts, cb, sch, jsonPtr + '/' + key, rootSchema, jsonPtr, key, schema);
  65. }
  66. }
  67. }
  68. }
  69. function escapeJsonPtr(str) {
  70. return str.replace(/~/g, '~0').replace(/\//g, '~1');
  71. }