@json-editor/json-editor 2.5.2 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/.eslintrc +5 -2
  2. package/.github/PULL_REQUEST_TEMPLATE.md +6 -6
  3. package/.github/workflows/build.yml +58 -0
  4. package/CHANGELOG.md +41 -1
  5. package/CONTRIBUTING.md +1 -1
  6. package/README.md +39 -4
  7. package/README_ADDON.md +65 -0
  8. package/config/codeceptjs_helpers.js +4 -0
  9. package/dist/jsoneditor.js +2 -2
  10. package/dist/nonmin/jsoneditor.js +3711 -3324
  11. package/dist/nonmin/jsoneditor.js.map +1 -1
  12. package/docs/cleave.html +1 -1
  13. package/docs/datetime.html +1 -1
  14. package/docs/describedby.html +1 -1
  15. package/docs/index.html +4 -2
  16. package/docs/materialize_css.html +1 -1
  17. package/docs/meta_schema.json +0 -1
  18. package/docs/radio.html +1 -1
  19. package/docs/select2.html +1 -1
  20. package/docs/selectize.html +1 -1
  21. package/docs/starrating.html +1 -1
  22. package/docs/wysiwyg.html +1 -1
  23. package/package.json +27 -26
  24. package/release-notes.md +9 -9
  25. package/src/core.js +1 -0
  26. package/src/defaults.js +182 -94
  27. package/src/editor.js +28 -9
  28. package/src/editors/array.js +20 -16
  29. package/src/editors/autocomplete.js +1 -0
  30. package/src/editors/base64.js +5 -4
  31. package/src/editors/button.js +2 -2
  32. package/src/editors/checkbox.js +3 -3
  33. package/src/editors/datetime.js +2 -2
  34. package/src/editors/info.js +1 -1
  35. package/src/editors/multiple.js +8 -2
  36. package/src/editors/multiselect.js +5 -3
  37. package/src/editors/object.js +35 -21
  38. package/src/editors/radio.js +9 -4
  39. package/src/editors/select.js +6 -6
  40. package/src/editors/signature.js +3 -2
  41. package/src/editors/starrating.js +5 -5
  42. package/src/editors/string.js +6 -4
  43. package/src/editors/table.js +24 -14
  44. package/src/editors/upload.js +4 -3
  45. package/src/editors/uuid.js +1 -1
  46. package/src/iconlibs/index.js +2 -0
  47. package/src/iconlibs/openiconic.js +28 -0
  48. package/src/schemaloader.js +112 -28
  49. package/src/theme.js +6 -3
  50. package/src/themes/bootstrap3.js +4 -4
  51. package/src/themes/bootstrap4.js +11 -3
  52. package/src/themes/html.js +1 -2
  53. package/src/themes/materialize.js +1 -1
  54. package/src/themes/spectre.js +11 -8
  55. package/src/themes/tailwind.js +1 -1
  56. package/src/validator.js +128 -16
  57. package/tests/codeceptjs/core_test.js +125 -1
  58. package/tests/codeceptjs/editors/array_test.js +13 -11
  59. package/tests/codeceptjs/editors/button_test.js +6 -1
  60. package/tests/codeceptjs/editors/issues/issue-gh-812_test.js +32 -0
  61. package/tests/codeceptjs/editors/number_test.js +1 -1
  62. package/tests/codeceptjs/editors/object_test.js +216 -100
  63. package/tests/codeceptjs/editors/programmatic-changes_test.js +3 -1
  64. package/tests/codeceptjs/editors/radio_test.js +10 -0
  65. package/tests/codeceptjs/editors/rating_test.js +10 -11
  66. package/tests/codeceptjs/editors/select_test.js +17 -15
  67. package/tests/codeceptjs/editors/stepper_test.js +13 -1
  68. package/tests/codeceptjs/editors/string_test.js +81 -80
  69. package/tests/codeceptjs/editors/table-confirm-delete_test.js +58 -56
  70. package/tests/codeceptjs/editors/tabs_test.js +12 -10
  71. package/tests/codeceptjs/editors/validation_test.js +10 -8
  72. package/tests/codeceptjs/meta-schema_test.js +13 -14
  73. package/tests/codeceptjs/schemaloader_test.js +13 -0
  74. package/tests/codeceptjs/steps_file.js +4 -3
  75. package/tests/codeceptjs/themes_test.js +31 -0
  76. package/tests/docker-compose.yml +4 -3
  77. package/tests/fixtures/validation.json +382 -1
  78. package/tests/pages/_demo.html +2 -0
  79. package/tests/pages/anyof.html +80 -0
  80. package/tests/pages/issues/issue-gh-812.html +110 -0
  81. package/tests/pages/issues/issue-gh-848.html +81 -0
  82. package/tests/pages/meta_schema.json +0 -1
  83. package/tests/pages/object-no-additional-properties.html +27 -12
  84. package/tests/pages/object-required-properties.html +43 -9
  85. package/tests/pages/object-show-opt-in.html +110 -0
  86. package/tests/pages/object-with-dependencies-array.html +56 -0
  87. package/tests/pages/oneof.html +103 -0
  88. package/tests/pages/read-only.html +19 -4
  89. package/tests/pages/stepper-manual.html +57 -0
  90. package/tests/pages/themes.html +2 -0
  91. package/tests/pages/translate-property.html +247 -0
  92. package/tests/pages/urn.html +93 -0
  93. package/tests/unit/core.spec.js +2 -0
  94. package/tests/unit/defaults.spec.js +4 -2
  95. package/tests/unit/editor.spec.js +2 -0
  96. package/tests/unit/editors/array.spec.js +86 -0
  97. package/tests/unit/editors/table.spec.js +91 -0
  98. package/tests/unit/schemaloader.spec.js +362 -3
  99. package/tests/unit/validator.spec.js +14 -2
@@ -1,3 +1,5 @@
1
+ /* global describe beforeEach it expect */
2
+
1
3
  import { SchemaLoader } from '../../src/schemaloader'
2
4
  import { createFakeServer } from 'sinon'
3
5
 
@@ -48,9 +50,36 @@ describe('SchemaLoader', () => {
48
50
  const urls = Object.keys(loader.refs)
49
51
  expect(urls.length).toEqual(1)
50
52
  })
53
+
54
+ it('load schema with urn: $ref', () => {
55
+ const schema = {
56
+ definitions: {
57
+ fname: {
58
+ id: 'urn:fname',
59
+ type: 'string',
60
+ default: 'John',
61
+ minLength: 4
62
+ },
63
+ lname: {
64
+ $id: 'urn:lname',
65
+ type: 'string',
66
+ default: 'Doe',
67
+ minLength: 4
68
+ }
69
+ },
70
+ type: 'object',
71
+ properties: {
72
+ fname: { $ref: 'urn:fname' },
73
+ lname: { $ref: 'urn:lname' }
74
+ }
75
+ }
76
+ loader.load(schema, schema => {}, fetchUrl, fileBase)
77
+ const urls = Object.keys(loader.refs)
78
+ expect(urls.length).toEqual(4)
79
+ })
51
80
  })
52
81
 
53
- describe('when external ref exists', () => {
82
+ describe('when external absolute ref exists', () => {
54
83
  it('should set oprion { ajax: true }', done => {
55
84
  const response = {
56
85
  type: 'string',
@@ -59,7 +88,7 @@ describe('SchemaLoader', () => {
59
88
  const server = createFakeServer()
60
89
  server.autoRespond = true
61
90
  window.XMLHttpRequest = server.xhr
62
- server.respondWith([
91
+ server.respondWith('/string.json', [
63
92
  200,
64
93
  { 'Content-Type': 'application/json' },
65
94
  JSON.stringify(response)
@@ -91,6 +120,46 @@ describe('SchemaLoader', () => {
91
120
  })
92
121
 
93
122
  describe('when external relative $ref exists', () => {
123
+ it('should set oprion { ajax: true }', done => {
124
+ const response = {
125
+ type: 'string',
126
+ minLength: 4
127
+ }
128
+ const server = createFakeServer()
129
+ server.autoRespond = true
130
+ window.XMLHttpRequest = server.xhr
131
+ server.respondWith('/string.json', [
132
+ 200,
133
+ { 'Content-Type': 'application/json' },
134
+ JSON.stringify(response)
135
+ ])
136
+ fetchUrl =
137
+ document.location.origin + document.location.pathname.toString()
138
+ loader = new SchemaLoader({ ajax: true })
139
+ fileBase = loader._getFileBase(document.location.toString())
140
+
141
+ const schema = {
142
+ type: 'object',
143
+ properties: {
144
+ fname: { $ref: 'string.json' },
145
+ lname: { $ref: 'string.json' }
146
+ }
147
+ }
148
+ loader.load(
149
+ schema,
150
+ schema => {
151
+ const urls = Object.keys(loader.refs)
152
+ expect(urls.length).toEqual(1)
153
+ done()
154
+ server.restore()
155
+ },
156
+ fetchUrl,
157
+ fileBase
158
+ )
159
+ })
160
+ })
161
+
162
+ describe('when external absolute-to-relative $ref exists', () => {
94
163
  it('can get refs recursively', done => {
95
164
  const schema1 = {
96
165
  type: 'object',
@@ -126,7 +195,6 @@ describe('SchemaLoader', () => {
126
195
  loader.load(
127
196
  schema1,
128
197
  schema => {
129
- console.log(loader.refs_with_info)
130
198
  expect(Object.keys(loader.refs).length).toBe(2)
131
199
  done()
132
200
  server.restore()
@@ -136,4 +204,295 @@ describe('SchemaLoader', () => {
136
204
  )
137
205
  })
138
206
  })
207
+
208
+ describe('when external relative-to-relative $ref exists', () => {
209
+ it('can get refs recursively', done => {
210
+ const schema1 = {
211
+ type: 'object',
212
+ properties: {
213
+ fname: { $ref: 'schema/main.json' },
214
+ lname: { $ref: 'schema/main.json' }
215
+ }
216
+ }
217
+ const schema2 = {
218
+ $ref: 'registry/sub.json'
219
+ }
220
+ const schema3 = {
221
+ type: 'string',
222
+ minLength: 4
223
+ }
224
+ const server = createFakeServer()
225
+ server.autoRespond = true
226
+ window.XMLHttpRequest = server.xhr
227
+ server.respondWith('/schema/main.json', [
228
+ 200,
229
+ { 'Content-Type': 'application/json' },
230
+ JSON.stringify(schema2)
231
+ ])
232
+ server.respondWith('/schema/registry/sub.json', [
233
+ 200,
234
+ { 'Content-Type': 'application/json' },
235
+ JSON.stringify(schema3)
236
+ ])
237
+ fetchUrl =
238
+ document.location.origin + document.location.pathname.toString()
239
+ loader = new SchemaLoader({ ajax: true })
240
+ fileBase = loader._getFileBase(document.location.toString())
241
+ loader.load(
242
+ schema1,
243
+ schema => {
244
+ console.log(loader.refs)
245
+ expect(Object.keys(loader.refs).length).toBe(2)
246
+ done()
247
+ server.restore()
248
+ },
249
+ fetchUrl,
250
+ fileBase
251
+ )
252
+ })
253
+ })
254
+
255
+ describe('when external absolute $ref with json pointer exists', () => {
256
+ it('can get refs', done => {
257
+ const schema1 = {
258
+ type: 'object',
259
+ properties: {
260
+ 'test-1': { $ref: '/common.schema.json#' },
261
+ 'test-2': { $ref: '/common.schema.json#/definitions/known-product' },
262
+ 'test-3': {
263
+ type: 'object',
264
+ properties: {
265
+ Product: { $ref: '/common.schema.json#/definitions/known-product' }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ const schema2 = {
271
+ definitions: {
272
+ 'known-product': {
273
+ title: 'product',
274
+ type: 'string',
275
+ enum: [ 'power', 'hydrogen', 'heat' ]
276
+ }
277
+ },
278
+ title: 'test',
279
+ properties: {
280
+ customer: { type: 'string' },
281
+ product: { $ref: '#/definitions/known-product' }
282
+ }
283
+ }
284
+ const server = createFakeServer()
285
+ server.autoRespond = true
286
+ window.XMLHttpRequest = server.xhr
287
+ server.respondWith('/common.schema.json', [
288
+ 200,
289
+ { 'Content-Type': 'application/json' },
290
+ JSON.stringify(schema2)
291
+ ])
292
+ fetchUrl =
293
+ document.location.origin + document.location.pathname.toString()
294
+ loader = new SchemaLoader({ ajax: true })
295
+ fileBase = loader._getFileBase(document.location.toString())
296
+ loader.load(
297
+ schema1,
298
+ schema => {
299
+ console.log(loader.refs)
300
+ expect(Object.keys(loader.refs).length).toBe(2)
301
+ done()
302
+ server.restore()
303
+ },
304
+ fetchUrl,
305
+ fileBase
306
+ )
307
+ })
308
+ })
309
+
310
+ describe('when external relative $ref with json pointer exists', () => {
311
+ it('can get refs', done => {
312
+ const schema1 = {
313
+ type: 'object',
314
+ properties: {
315
+ 'test-1': { $ref: 'common.schema.json#' },
316
+ 'test-2': { $ref: 'common.schema.json#/definitions/known-product' },
317
+ 'test-3': {
318
+ type: 'object',
319
+ properties: {
320
+ Product: { $ref: 'common.schema.json#/definitions/known-product' }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ const schema2 = {
326
+ definitions: {
327
+ 'known-product': {
328
+ title: 'product',
329
+ type: 'string',
330
+ enum: [ 'power', 'hydrogen', 'heat' ]
331
+ }
332
+ },
333
+ title: 'test',
334
+ properties: {
335
+ customer: { type: 'string' },
336
+ product: { $ref: '#/definitions/known-product' }
337
+ }
338
+ }
339
+ const server = createFakeServer()
340
+ server.autoRespond = true
341
+ window.XMLHttpRequest = server.xhr
342
+ server.respondWith('/common.schema.json', [
343
+ 200,
344
+ { 'Content-Type': 'application/json' },
345
+ JSON.stringify(schema2)
346
+ ])
347
+ fetchUrl =
348
+ document.location.origin + document.location.pathname.toString()
349
+ loader = new SchemaLoader({ ajax: true })
350
+ fileBase = loader._getFileBase(document.location.toString())
351
+ loader.load(
352
+ schema1,
353
+ schema => {
354
+ console.log(loader.refs)
355
+ expect(Object.keys(loader.refs).length).toBe(2)
356
+ done()
357
+ server.restore()
358
+ },
359
+ fetchUrl,
360
+ fileBase
361
+ )
362
+ })
363
+ })
364
+
365
+ describe('when external ref exists with json pointer', () => {
366
+ it('should get ref and resolve json pointer', done => {
367
+ const response = {
368
+ definitions: {
369
+ fruits: {
370
+ enum: [
371
+ 'apple',
372
+ 'banana',
373
+ 'cherry'
374
+ ]
375
+ }
376
+ }
377
+ }
378
+ const server = createFakeServer()
379
+ server.autoRespond = true
380
+ window.XMLHttpRequest = server.xhr
381
+ server.respondWith([
382
+ 200,
383
+ { 'Content-Type': 'application/json' },
384
+ JSON.stringify(response)
385
+ ])
386
+ fetchUrl =
387
+ document.location.origin + document.location.pathname.toString()
388
+ loader = new SchemaLoader({ ajax: true })
389
+ fileBase = loader._getFileBase(document.location.toString())
390
+
391
+ const schema = {
392
+ type: 'object',
393
+ properties: {
394
+ fruits: { $ref: '/fruits.json#/definitions/fruits' }
395
+ }
396
+ }
397
+ loader.load(
398
+ schema,
399
+ schema => {
400
+ const urls = Object.keys(loader.refs)
401
+ expect(urls.length).toEqual(1)
402
+ expect(urls[0]).toEqual('/fruits.json#/definitions/fruits')
403
+ expect(loader.refs['/fruits.json#/definitions/fruits']).toEqual({ enum: ['apple', 'banana', 'cherry'] })
404
+ done()
405
+ server.restore()
406
+ },
407
+ fetchUrl,
408
+ fileBase
409
+ )
410
+ })
411
+ })
412
+
413
+ describe('when resolving undeclared URN $ref', () => {
414
+ it('can get refs recursively', done => {
415
+ const schema1 = {
416
+ type: 'object',
417
+ properties: {
418
+ fname: { $ref: 'urn:main' },
419
+ lname: { $ref: 'urn:sub' }
420
+ }
421
+ }
422
+ const schema2 = {
423
+ definitions: {
424
+ name: {
425
+ id: 'urn:main',
426
+ $ref: 'urn:sub'
427
+ }
428
+ }
429
+ }
430
+ const schema3 = {
431
+ definitions: {
432
+ name: {
433
+ $id: 'urn:sub',
434
+ type: 'string',
435
+ default: 'Waldo',
436
+ minLength: 4
437
+ }
438
+ }
439
+ }
440
+ loader = new SchemaLoader({ urn_resolver: (urn, callback) => {
441
+ if (urn === 'urn:main') {
442
+ callback(JSON.stringify(schema2))
443
+ return true
444
+ }
445
+ if (urn === 'urn:sub') {
446
+ callback(JSON.stringify(schema3))
447
+ return true
448
+ }
449
+ return false
450
+ }})
451
+ loader.load(
452
+ schema1,
453
+ schema => {
454
+ console.log(loader.refs_with_info)
455
+ expect(Object.keys(loader.refs).length).toBe(4)
456
+ done()
457
+ }
458
+ )
459
+ })
460
+ })
461
+
462
+ describe('when resolving undeclared URN $ref with fragment', () => {
463
+ it('can get refs recursively', done => {
464
+ const schema1 = {
465
+ type: 'object',
466
+ properties: {
467
+ fname: { $ref: 'urn:main#/definitions/name' },
468
+ lname: { $ref: 'urn:main#/definitions/name' }
469
+ }
470
+ }
471
+ const schema2 = {
472
+ definitions: {
473
+ name: {
474
+ $id: 'urn:main',
475
+ type: 'string',
476
+ default: 'Waldo',
477
+ minLength: 4
478
+ }
479
+ }
480
+ }
481
+ loader = new SchemaLoader({ urn_resolver: (urn, callback) => {
482
+ if (urn === 'urn:main') {
483
+ callback(JSON.stringify(schema2))
484
+ return true
485
+ }
486
+ return false
487
+ }})
488
+ loader.load(
489
+ schema1,
490
+ schema => {
491
+ console.log(loader.refs_with_info)
492
+ expect(Object.keys(loader.refs).length).toBe(2)
493
+ done()
494
+ }
495
+ )
496
+ })
497
+ })
139
498
  })
@@ -1,3 +1,5 @@
1
+ /* global describe beforeAll beforeEach afterEach afterAll it expect */
2
+
1
3
  import { JSONEditor } from '../../src/core'
2
4
  import { Validator } from '../../src/validator'
3
5
  import { defaults } from '../../src/defaults'
@@ -6,6 +8,7 @@ import fixtureString from '../fixtures/string.json'
6
8
  import fixtureRecursive from '../fixtures/recursive.json'
7
9
  import * as math from 'mathjs'
8
10
  import { createFakeServer } from 'sinon'
11
+ import * as deepEqual from 'fast-deep-equal';
9
12
 
10
13
  describe('Validator', () => {
11
14
  it('mathjs test', () => {
@@ -36,8 +39,8 @@ describe('Validation Test', () => {
36
39
  server.autoRespond = true
37
40
  window.XMLHttpRequest = server.xhr
38
41
  const response = {
39
- 'string': fixtureString,
40
- 'recursive': fixtureRecursive
42
+ string: fixtureString,
43
+ recursive: fixtureRecursive
41
44
  }
42
45
  server.respondWith(/(\w+)\.json/, (xhr, name) => {
43
46
  xhr.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify(response[name]))
@@ -77,6 +80,15 @@ describe('Validation Test', () => {
77
80
  done()
78
81
  })
79
82
  })
83
+
84
+ it(`does not change valid data ${i + 1}`, (done) => {
85
+ editor.on('ready', () => {
86
+ editor.setValue(v)
87
+ expect(deepEqual(editor.getValue(), v)).toBe(true)
88
+ done()
89
+ })
90
+ })
91
+
80
92
  })
81
93
  spec.invalid.forEach((v, i) => {
82
94
  it(`invalid data ${i + 1}`, (done) => {