@json-editor/json-editor 2.12.0 → 2.13.0

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.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@json-editor/json-editor",
3
3
  "title": "JSONEditor",
4
4
  "description": "JSON Schema based editor",
5
- "version": "2.12.0",
5
+ "version": "2.13.0",
6
6
  "main": "dist/jsoneditor.js",
7
7
  "author": {
8
8
  "name": "Jeremy Dorn",
package/src/editor.js CHANGED
@@ -510,6 +510,7 @@ export class AbstractEditor {
510
510
 
511
511
  onWatchedFieldChange () {
512
512
  let vars
513
+
513
514
  if (this.header_template) {
514
515
  vars = extend(this.getWatchedFieldValues(), {
515
516
  key: this.key,
@@ -518,6 +519,23 @@ export class AbstractEditor {
518
519
  i1: (this.key * 1 + 1),
519
520
  title: this.getTitle()
520
521
  })
522
+
523
+ // object properties
524
+ if (Object.keys(this.editors).length) {
525
+ Object.keys(this.editors).forEach((key) => {
526
+ const editor = this.editors[key]
527
+
528
+ if (editor.schema && editor.schema.enum && editor.schema.options && editor.schema.options.enum_titles) {
529
+ const enumIndex = editor.schema.enum.indexOf(editor.value)
530
+ const enumTitle = editor.options.enum_titles[enumIndex]
531
+ vars.properties = {}
532
+ vars.properties[key] = {
533
+ enumTitle: enumTitle
534
+ }
535
+ }
536
+ })
537
+ }
538
+
521
539
  const headerText = this.header_template(vars)
522
540
 
523
541
  if (headerText !== this.header_text) {
@@ -24,7 +24,6 @@ export class ButtonEditor extends AbstractEditor {
24
24
 
25
25
  /* Get options, either global options from "this.defaults.options.button" or */
26
26
  /* single property options from schema "options.button" */
27
- const title = this.translateProperty(this.schema.title) || this.key
28
27
  const options = this.expandCallbacks('button', extend({}, {
29
28
  icon: '',
30
29
  validated: false,
@@ -34,8 +33,15 @@ export class ButtonEditor extends AbstractEditor {
34
33
  }
35
34
  }, this.defaults.options.button || {}, this.options.button || {}))
36
35
 
36
+ const title = this.translateProperty(options.text || this.schema.title) || this.key
37
+
37
38
  this.input = this.getButton(title, options.icon, title)
38
- this.input.addEventListener('click', options.action, false)
39
+
40
+ if (typeof options.action !== 'function') {
41
+ window.alert(`No button action defined for "${this.path}"`)
42
+ } else {
43
+ this.input.addEventListener('click', options.action, false)
44
+ }
39
45
 
40
46
  if (this.schema.readOnly || this.schema.readonly || this.schema.template) {
41
47
  this.disable(true)
@@ -23,7 +23,8 @@ export class SimplemdeEditor extends StringEditor {
23
23
  options = this.expandCallbacks('simplemde', extend({}, {
24
24
  height: 300
25
25
  }, this.defaults.options.simplemde || {}, this.options.simplemde || {}, {
26
- element: this.input
26
+ element: this.input,
27
+ forceSync: true
27
28
  }))
28
29
 
29
30
  this.simplemde_instance = new window.SimpleMDE(options)
package/src/resolvers.js CHANGED
@@ -1,11 +1,14 @@
1
- /* Use "multiple" as a fall back for everything */
1
+ /* Use "multiple" as a fallback for everything */
2
2
  const defaultResolver = schema => typeof schema.type !== 'string' && 'multiple'
3
3
 
4
+ /* If the type is a script type, then presume the Editor's type is "string" until later resolvers decide otherwise */
5
+ const defaultResolverString = schema => typeof schema.type === 'string' && 'string'
6
+
4
7
  /* If the type is not set but properties are defined, we can infer the type is actually object */
5
8
  const object = schema => !schema.type && schema.properties && 'object'
6
9
 
7
- /* If the type is set and it's a basic type, use the primitive editor */
8
- const primitive = schema => typeof schema.type === 'string' && schema.type
10
+ /* If type is set, and it's a basic JSON type, use the primitive editor */
11
+ const primitive = schema => typeof schema.type === 'string' && ['string', 'number', 'integer', 'boolean', 'null', 'array', 'object'].includes(schema.type) && schema.type
9
12
 
10
13
  /* Use specialized editor for signatures */
11
14
  const signature = schema => schema.type === 'string' && schema.format === 'signature' && 'signature'
@@ -129,4 +132,4 @@ const ip = schema => schema.type === 'string' && ['ip', 'ipv4', 'ipv6', 'hostnam
129
132
  const colorPicker = schema => schema.type === 'string' && schema.format === 'color' && 'colorpicker'
130
133
 
131
134
  /* Export resolvers in order of discovery, first to last */
132
- export const resolvers = [colorPicker, ip, ace, xhtml, markdown, jodit, autoComplete, uuid, info, button, stepper, describeBy, starratings, date, oneOf, ifThenElse, arraysOfStrings, enumeratedProperties, enumSource, table, upload, base64, any, boolean, signature, primitive, object, defaultResolver]
135
+ export const resolvers = [colorPicker, ip, ace, xhtml, markdown, jodit, autoComplete, uuid, info, button, stepper, describeBy, starratings, date, oneOf, ifThenElse, arraysOfStrings, enumeratedProperties, enumSource, table, upload, base64, any, boolean, signature, primitive, object, defaultResolver, defaultResolverString]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "tests": "./**/*_test.js",
3
- "timeout": 10000,
3
+ "timeout": 30,
4
4
  "output": "./output",
5
5
  "plugins": {
6
6
  "pauseOnFail": {}
@@ -7,18 +7,18 @@ Scenario('should display contains validation errors @contains', ({ I }) => {
7
7
  I.waitForElement('.je-ready')
8
8
  I.waitForText('No items match contains')
9
9
  I.click('.json-editor-btn-add')
10
+ I.waitForInvisible('.alert-danger')
10
11
  I.dontSee('No items match contains')
11
12
  })
12
13
 
13
14
  Scenario('should display @minContains validation errors @contains', ({ I }) => {
14
15
  I.amOnPage('minContains.html')
15
16
  I.waitForElement('.je-ready')
16
- I.dontSee('No items match contains')
17
17
  I.waitForText('Contains match count 0 is less than minimum contains count of 2')
18
18
  I.click('.json-editor-btn-add')
19
- I.dontSee('No items match contains')
20
19
  I.waitForText('Contains match count 1 is less than minimum contains count of 2')
21
20
  I.click('.json-editor-btn-add')
21
+ I.waitForInvisible('.alert-danger')
22
22
  I.dontSee('No items match contains')
23
23
  I.dontSee('minimum contains count of 2')
24
24
  })
@@ -28,6 +28,7 @@ Scenario('should display @maxContains validation errors @contains', ({ I }) => {
28
28
  I.waitForElement('.je-ready')
29
29
  I.waitForText('No items match contains')
30
30
  I.click('.json-editor-btn-add')
31
+ I.waitForInvisible('.alert-danger')
31
32
  I.dontSee('No items match contains')
32
33
  I.click('.json-editor-btn-add')
33
34
  I.dontSee('No items match contains')
@@ -9,6 +9,7 @@ Scenario('@dependentSchemas should display validation errors', ({ I }) => {
9
9
  I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
10
10
  I.waitForText('Object is missing the required property \'billing_address\'')
11
11
  I.click('[data-schemapath="root.billing_address"] .json-editor-opt-in')
12
+ I.waitForInvisible('.alert-danger')
12
13
  I.dontSee('Object is missing the required property \'billing_address\'')
13
14
  I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
14
15
  I.dontSee('Object is missing the required property \'billing_address\'')
@@ -89,18 +89,18 @@ Scenario('should set and get individual values', async ({ I }) => {
89
89
  I.waitForValue('.value', '"john kaminski"')
90
90
  })
91
91
 
92
- Scenario('should watch a specific field for changes', async ({ I }) => {
92
+ Scenario('should watch a specific field for changes @core @change', async ({ I }) => {
93
93
  I.amOnPage('core.html')
94
94
  I.dontSeeElement('.name-changed')
95
95
  I.click('.set-individual-value')
96
- I.seeElement('.name-changed')
96
+ I.waitForElement('.name-changed')
97
97
  })
98
98
 
99
- Scenario('should watch form for changes', async ({ I }) => {
99
+ Scenario('should watch form for changes @core @change', async ({ I }) => {
100
100
  I.amOnPage('core.html')
101
101
  I.dontSeeElement('.form-changed')
102
102
  I.click('.set-value')
103
- I.seeElement('.form-changed')
103
+ I.waitForElement('.form-changed')
104
104
  })
105
105
 
106
106
  Scenario('should change the form if form_name_root option is set @core', async ({ I }) => {
@@ -1,6 +1,6 @@
1
1
  /* global Feature Scenario */
2
2
 
3
- Feature('Advanced Editor')
3
+ Feature('Advanced Editor @advance-editor')
4
4
 
5
5
  Scenario('test validation & delete', ({ I }) => {
6
6
  I.amOnPage('advanced.html')
@@ -4,6 +4,13 @@ const { DEFAULT_WAIT_TIME } = require('../test-config')
4
4
 
5
5
  Feature('array')
6
6
 
7
+ Scenario('Should display properties enum titles in items headerTemplate @headerTemplate', async ({ I }) => {
8
+ I.amOnPage('array-header-template.html')
9
+ I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
10
+ I.waitForText('Dog', DEFAULT_WAIT_TIME, '.nav-link span')
11
+ I.waitForText('Cat', DEFAULT_WAIT_TIME, '.nav-link span')
12
+ })
13
+
7
14
  Scenario('Should set buttons states correctly @button_state_mode', async ({ I }) => {
8
15
  I.amOnPage('button_state_mode_1.html')
9
16
  I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
@@ -5,7 +5,9 @@ Feature('autocomplete')
5
5
  Scenario('autocomplete should work @autocomplete', async ({ I }) => {
6
6
  I.amOnPage('autocomplete.html')
7
7
  I.waitForElement('.je-ready', 10)
8
- I.fillField('root', 'ir')
8
+ I.click('[name="root"]')
9
+ I.pressKey('i')
10
+ I.pressKey('r')
9
11
  I.waitForText('iran', 20, '.autocomplete-result-list')
10
12
  I.waitForText('iraq', 20, '.autocomplete-result-list')
11
13
  I.click('iraq', '.autocomplete-result:nth-child(2)')
@@ -4,7 +4,7 @@ const { DEFAULT_WAIT_TIME } = require('../test-config')
4
4
 
5
5
  Feature('Tabs')
6
6
 
7
- Scenario('test top-tabs', ({ I }) => {
7
+ Scenario('test @top-tabs', ({ I }) => {
8
8
  I.amOnPage('tabs.html')
9
9
  I.waitForElement('[data-schemapath="root"] .json-editor-btn-add')
10
10
  I.click('[data-schemapath="root"] .json-editor-btn-add')
@@ -7,12 +7,12 @@ Scenario('GitHub issue 1338 should remain fixed @issue-1338', async ({ I }) => {
7
7
  I.waitForText('Value required')
8
8
  I.fillField('[id="root[field_a]"]', 'test')
9
9
  I.pressKey('Tab')
10
- I.waitForElement('.invalid-feedback')
10
+ I.waitForInvisible('.invalid-feedback')
11
11
  I.dontSee('Value required')
12
12
  I.refreshPage()
13
13
  I.waitForText('Value required')
14
14
  I.fillField('[id="root[field_b]"]', 'test')
15
15
  I.pressKey('Tab')
16
- I.waitForElement('.invalid-feedback')
16
+ I.waitForInvisible('.invalid-feedback')
17
17
  I.dontSee('Value required')
18
18
  })
@@ -0,0 +1,12 @@
1
+ /* global Feature Scenario */
2
+
3
+ Feature('issues')
4
+
5
+ Scenario('GitHub issue 1431 should remain fixed @issue-1431', async ({ I }) => {
6
+ I.amOnPage('issues/issue-gh-1431.html')
7
+ I.waitForElement('.je-ready')
8
+ I.waitForElement('.CodeMirror')
9
+ I.click('.CodeMirror')
10
+ I.pressKeys('simple-mde')
11
+ I.waitForValue('#value', '{"name":"simple-mde"}')
12
+ })
@@ -0,0 +1,12 @@
1
+ /* global Feature Scenario */
2
+
3
+ Feature('issues')
4
+
5
+ Scenario('GitHub issue 1439 should remain fixed @issue-1439', async ({ I }) => {
6
+ I.amOnPage('issues/issue-gh-1439.html')
7
+ I.waitForElement('.je-ready')
8
+ I.waitForElement('[name="root[wrong]"]')
9
+ I.waitForElement('[data-schemapath="root.correct"] button')
10
+ I.waitForText('Button text')
11
+ I.waitForValue('#value', '{"wrong":""}')
12
+ })
@@ -0,0 +1,59 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <title>array-header-template</title>
6
+ <script src="../../dist/jsoneditor.js"></script>
7
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
8
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
9
+ </head>
10
+ <body>
11
+
12
+ <div class="container">
13
+ <div id='editor-container'></div>
14
+ </div>
15
+
16
+ <script>
17
+ const editorContainer = document.querySelector('#editor-container')
18
+ const schema1 = {
19
+ "title": "Pets",
20
+ "format": "tabs",
21
+ "type": "array",
22
+ "minItems": 1,
23
+ "default": [
24
+ {
25
+ "pet": "pet_1"
26
+ },
27
+ {
28
+ "pet": "pet_2"
29
+ }
30
+ ],
31
+ "items": {
32
+ "title": "Pets",
33
+ "type": "object",
34
+ "headerTemplate": "{{ properties.pet.enumTitle }}",
35
+ "properties": {
36
+ "pet": {
37
+ "title": "Pet",
38
+ "type": "string",
39
+ "enum": [ "pet_1", "pet_2" ],
40
+ "options": {
41
+ "enum_titles": [ "Dog", "Cat" ]
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ const editor = new JSONEditor(editorContainer, {
49
+ schema: schema1,
50
+ theme: 'bootstrap4',
51
+ iconlib: 'fontawesome',
52
+ disable_collapse: true,
53
+ disable_edit_json: true,
54
+ disable_properties: true
55
+ })
56
+ </script>
57
+
58
+ </body>
59
+ </html>
@@ -17,7 +17,7 @@
17
17
  'title': 'test',
18
18
  'properties': {
19
19
  'search': {
20
- 'type': 'button',
20
+ 'format': 'button',
21
21
  'title': 'Search',
22
22
  'options': {
23
23
  'button': {
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>GitHub Issue 1431</title>
6
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
7
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
9
+ <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
10
+ <script src="../../../dist/jsoneditor.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="container">
14
+ <textarea class="form-control" id="value" cols="30" rows="10"></textarea>
15
+ <a href="https://github.com/json-editor/json-editor/issues/1431">GitHub Issue 1431</a>
16
+ <div id='editor_holder'></div>
17
+ </div>
18
+
19
+ <script>
20
+ var value = document.querySelector('#value')
21
+ var defaultSchema = {
22
+ "title": "Person",
23
+ "type": "object",
24
+ "required": [
25
+ "name"
26
+ ],
27
+ "properties": {
28
+ "name": {
29
+ "type": "string",
30
+ "format": "markdown"
31
+ }
32
+ }
33
+ }
34
+
35
+ var editor = new JSONEditor(document.getElementById('editor_holder'), {
36
+ iconlib: 'fontawesome5',
37
+ schema: defaultSchema,
38
+ show_errors: 'always',
39
+ theme: 'bootstrap4'
40
+ })
41
+
42
+ editor.on('change', function () {
43
+ value.value = JSON.stringify(editor.getValue())
44
+ })
45
+
46
+ window.addEventListener('click', (e) => {console.log(e.target)})
47
+ </script>
48
+ </body>
49
+ </html>
@@ -0,0 +1,69 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>GitHub Issue 1439</title>
6
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
7
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
9
+ <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
10
+ <script src="../../../dist/jsoneditor.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="container">
14
+ <textarea class="form-control" id="value" cols="30" rows="10"></textarea>
15
+ <a href="https://github.com/json-editor/json-editor/issues/1439">GitHub Issue 1439</a>
16
+ <div id='editor_holder'></div>
17
+ </div>
18
+
19
+ <script>
20
+ var value = document.querySelector('#value')
21
+ var defaultSchema = {
22
+ "type": "object",
23
+ "properties": {
24
+ "wrong": {
25
+ "type": "button",
26
+ "title": "Search",
27
+ "options": {
28
+ "button": {
29
+ "icon": "search",
30
+ "action": "myAction",
31
+ "validated": true
32
+ }
33
+ }
34
+ },
35
+ "correct": {
36
+ "format": "button",
37
+ "options": {
38
+ "button": {
39
+ "text": "Button text",
40
+ "icon": "search",
41
+ "action": "myAction",
42
+ "validated": true
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ JSONEditor.defaults.callbacks = {
50
+ "button" : {
51
+ "myAction" : function () {
52
+ alert('Button action')
53
+ }
54
+ }
55
+ }
56
+
57
+ var editor = new JSONEditor(document.getElementById('editor_holder'), {
58
+ iconlib: 'fontawesome5',
59
+ schema: defaultSchema,
60
+ show_errors: 'always',
61
+ theme: 'bootstrap4'
62
+ })
63
+
64
+ editor.on('change', function () {
65
+ value.value = JSON.stringify(editor.getValue())
66
+ })
67
+ </script>
68
+ </body>
69
+ </html>
@@ -496,7 +496,6 @@
496
496
  'type': 'string',
497
497
  'propertyOrder': 4
498
498
  },
499
-
500
499
  'enum': {
501
500
  'type': 'array',
502
501
  'minItems': 1,
@@ -504,6 +503,17 @@
504
503
  'propertyOrder': 50,
505
504
  'format': 'table'
506
505
  },
506
+ 'const': {
507
+ 'type': [
508
+ 'object',
509
+ 'array',
510
+ 'string',
511
+ 'number',
512
+ 'integer',
513
+ 'boolean',
514
+ 'null'
515
+ ]
516
+ },
507
517
  'enumSource': {
508
518
  'oneOf': [
509
519
  {