index.js 2.4 KB

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