Skip to content

Commit

Permalink
Merge branch 'josdejong:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
andyquinterom authored Jul 20, 2021
2 parents 7188a60 + eb84c4e commit b76c57a
Show file tree
Hide file tree
Showing 10 changed files with 1,044 additions and 1,785 deletions.
19 changes: 19 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
https://github.com/josdejong/jsoneditor


## 2021-06-30, version 9.5.1

- Upgrade to `[email protected]`.


## 2021-06-05, version 9.5.0

- Implemented new method `JSONEditor.validate(): Promise<ValidationError[]>`.
Thanks @ChrisAcrobat.


## 2021-06-02, version 9.4.2

- Fix #1311: exception being thrown under certain conditions when switching
from `code` mode to `preview` mode.
- Rename spin animation of `selectr` to prevent conflicts with tailwind,
see #1333. Thanks @mdix.


## 2021-04-25, version 9.4.1

- Improvements in the Korean translation. Thanks @luasenvy.
Expand Down
19 changes: 18 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,17 @@ Constructs a new JSONEditor.

Also see the option `schema` for JSON schema validation.

- `{function} onValidationError(errors)`
- `{function} onValidationError(errors: ValidationError[])`

Set a callback function for validation and parse errors. Available in all modes.
The `ValidationError` contains a `type`, `path`, and `message`.

On validation of the json, if errors of any kind were found this callback is invoked with the errors data.

On change, the callback will be invoked only if errors were changed.

See also method `JSONEditor.validate()`.

Example:

```js
Expand Down Expand Up @@ -882,6 +885,20 @@ valid JSON and the editor is in mode `tree`, `view`, or `form`.

Contents of the editor as string.

#### `JSONEditor.validate()`

Validate the JSON document against the configured JSON schema or custom validator.
See also the `onValidationError` callback.

*Returns:*

- `{Promise<ValidationError[]>} errorsPromise`

Returns a promise which resolves with the current validation errors,
or an empty list when there are no errors. The `ValidationError` contains
a `type`, `path`, and `message`.


### Static properties

- `{string[]} JSONEditor.VALID_OPTIONS`
Expand Down
2 changes: 1 addition & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const log = require('fancy-log')
const format = require('date-format')
const concatCss = require('gulp-concat-css')
const minifyCSS = require('gulp-clean-css')
const sass = require('gulp-sass')
const sass = require('gulp-sass')(require('sass'))
const mkdirp = require('mkdirp')
const webpack = require('webpack')
const uglify = require('uglify-js')
Expand Down
2,647 changes: 916 additions & 1,731 deletions package-lock.json

Large diffs are not rendered by default.

23 changes: 12 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsoneditor",
"version": "9.4.1",
"version": "9.5.1",
"main": "./dist/jsoneditor.min.js",
"description": "A web-based tool to view, edit, format, and validate JSON",
"tags": [
Expand Down Expand Up @@ -30,32 +30,33 @@
"ajv": "^6.12.6",
"javascript-natural-sort": "^0.7.1",
"jmespath": "^0.15.0",
"jsonrepair": "^2.2.0",
"jsonrepair": "^2.2.1",
"json-source-map": "^0.6.1",
"mobius1-selectr": "^2.4.13",
"picomodal": "^3.0.0",
"vanilla-picker": "^2.11.2"
},
"devDependencies": {
"@babel/core": "7.13.16",
"@babel/preset-env": "7.13.15",
"@babel/register": "7.13.16",
"@babel/core": "7.14.6",
"@babel/preset-env": "7.14.7",
"@babel/register": "7.14.5",
"babel-loader": "8.2.2",
"btoa": "1.2.1",
"date-format": "3.0.0",
"fancy-log": "1.3.3",
"gulp": "4.0.2",
"gulp-clean-css": "4.3.0",
"gulp-concat-css": "3.1.0",
"gulp-sass": "4.1.0",
"jsdom": "16.5.3",
"gulp-sass": "5.0.0",
"jsdom": "16.6.0",
"json-loader": "0.5.7",
"mkdirp": "1.0.4",
"mocha": "8.3.2",
"source-map-loader": "2.0.1",
"mocha": "9.0.1",
"sass": "1.35.1",
"source-map-loader": "3.0.0",
"standard": "16.0.3",
"uglify-js": "3.13.4",
"webpack": "5.35.1"
"uglify-js": "3.13.10",
"webpack": "5.41.1"
},
"files": [
"dist",
Expand Down
10 changes: 5 additions & 5 deletions src/js/assets/selectr/selectr.scss
Original file line number Diff line number Diff line change
Expand Up @@ -405,16 +405,16 @@
-webkit-transform-origin: 50% 0 0;
transform-origin: 50% 0 0;

-moz-animation: 500ms linear 0s normal forwards infinite running spin;
-webkit-animation: 500ms linear 0s normal forwards infinite running spin;
animation: 500ms linear 0s normal forwards infinite running spin;
-moz-animation: 500ms linear 0s normal forwards infinite running selectr-spin;
-webkit-animation: 500ms linear 0s normal forwards infinite running selectr-spin;
animation: 500ms linear 0s normal forwards infinite running selectr-spin;
border-width: 3px;
border-style: solid;
border-color: #aaa #ddd #ddd;
border-radius: 50%;
}

@-webkit-keyframes spin {
@-webkit-keyframes selectr-spin {
0% {
-webkit-transform: rotate(0deg) translate3d(0px, -50%, 0px);
transform: rotate(0deg) translate3d(0px, -50%, 0px);
Expand All @@ -424,7 +424,7 @@
transform: rotate(360deg) translate3d(0px, -50%, 0px);
}
}
@keyframes spin {
@keyframes selectr-spin {
0% {
-webkit-transform: rotate(0deg) translate3d(0px, -50%, 0px);
transform: rotate(0deg) translate3d(0px, -50%, 0px);
Expand Down
53 changes: 35 additions & 18 deletions src/js/textmode.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ textmode.create = function (container, options = {}) {
this.lastSchemaErrors = undefined

// create a debounced validate function
this._debouncedValidate = debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this._debouncedValidate = debounce(this._validateAndCatch.bind(this), this.DEBOUNCE_INTERVAL)

this.width = container.clientWidth
this.height = container.clientHeight
Expand Down Expand Up @@ -346,7 +346,7 @@ textmode.create = function (container, options = {}) {
this.errorTable = new ErrorTable({
errorTableVisible: this.mode === 'text',
onToggleVisibility: function () {
me.validate()
me._validateAndCatch()
},
onFocusLine: function (line) {
me.isFocused = true
Expand Down Expand Up @@ -434,7 +434,11 @@ textmode._onChange = function () {
}

// enable/disable undo/redo buttons
setTimeout(() => this._updateHistoryButtons())
setTimeout(() => {
if (this._updateHistoryButtons) {
this._updateHistoryButtons()
}
})

// validate JSON schema (if configured)
this._debouncedValidate()
Expand Down Expand Up @@ -822,7 +826,11 @@ textmode._setText = function (jsonText, clearHistory) {
})
}

setTimeout(() => this._updateHistoryButtons())
setTimeout(() => {
if (this._updateHistoryButtons) {
this._updateHistoryButtons()
}
})
}

// validate JSON schema
Expand Down Expand Up @@ -877,22 +885,22 @@ textmode.validate = function () {
this.validationSequence = (this.validationSequence || 0) + 1
const me = this
const seq = this.validationSequence
validateCustom(json, this.options.onValidate)
return validateCustom(json, this.options.onValidate)
.then(customValidationErrors => {
// only apply when there was no other validation started whilst resolving async results
if (seq === me.validationSequence) {
const errors = schemaErrors.concat(parseErrors).concat(customValidationErrors)
me._renderErrors(errors)
if (typeof this.options.onValidationError === 'function') {
if (isValidationErrorChanged(errors, this.lastSchemaErrors)) {
this.options.onValidationError.call(this, errors)
}
this.lastSchemaErrors = errors
if (
typeof this.options.onValidationError === 'function' &&
isValidationErrorChanged(errors, this.lastSchemaErrors)
) {
this.options.onValidationError.call(this, errors)
}
this.lastSchemaErrors = errors
}
})
.catch(err => {
console.error('Custom validation function did throw an error', err)

return this.lastSchemaErrors
})
} catch (err) {
if (this.getText()) {
Expand All @@ -911,15 +919,24 @@ textmode.validate = function () {

this._renderErrors(parseErrors)

if (typeof this.options.onValidationError === 'function') {
if (isValidationErrorChanged(parseErrors, this.lastSchemaErrors)) {
this.options.onValidationError.call(this, parseErrors)
}
this.lastSchemaErrors = parseErrors
if (
typeof this.options.onValidationError === 'function' &&
isValidationErrorChanged(parseErrors, this.lastSchemaErrors)
) {
this.options.onValidationError.call(this, parseErrors)
}
this.lastSchemaErrors = parseErrors

return Promise.resolve(this.lastSchemaErrors)
}
}

textmode._validateAndCatch = function () {
this.validate().catch(err => {
console.error('Error running validation:', err)
})
}

textmode._renderErrors = function (errors) {
const jsonText = this.getText()
const errorPaths = []
Expand Down
33 changes: 20 additions & 13 deletions src/js/treemode.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ treemode._setOptions = function (options) {
this.setSchema(this.options.schema, this.options.schemaRefs)

// create a debounced validate function
this._debouncedValidate = debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this._debouncedValidate = debounce(this._validateAndCatch.bind(this), this.DEBOUNCE_INTERVAL)

if (options.onSelectionChange) {
this.onSelectionChange(options.onSelectionChange)
Expand Down Expand Up @@ -214,7 +214,7 @@ treemode.set = function (json) {
this._setRoot(node)

// validate JSON schema (if configured)
this.validate()
this._validateAndCatch()

// expand
const recurse = false
Expand Down Expand Up @@ -254,7 +254,7 @@ treemode.update = function (json) {
this.onChangeDisabled = false

// validate JSON schema
this.validate()
this._validateAndCatch()

// update search result if any
if (this.searchBox && !this.searchBox.isEmpty()) {
Expand Down Expand Up @@ -588,28 +588,35 @@ treemode.validate = function () {
this.validationSequence++
const me = this
const seq = this.validationSequence
this._validateCustom(json)
return this._validateCustom(json)
.then(customValidationErrors => {
// only apply when there was no other validation started whilst resolving async results
if (seq === me.validationSequence) {
const errorNodes = [].concat(schemaErrors, customValidationErrors || [])
me._renderValidationErrors(errorNodes)
if (typeof this.options.onValidationError === 'function') {
if (isValidationErrorChanged(errorNodes, this.lastSchemaErrors)) {
this.options.onValidationError.call(this, errorNodes)
}
this.lastSchemaErrors = errorNodes
if (
typeof this.options.onValidationError === 'function' &&
isValidationErrorChanged(errorNodes, this.lastSchemaErrors)
) {
this.options.onValidationError.call(this, errorNodes)
}

this.lastSchemaErrors = errorNodes
}
})
.catch(err => {
console.error(err)

return this.lastSchemaErrors
})
} catch (err) {
console.error(err)
return Promise.reject(err)
}
}

treemode._validateAndCatch = function () {
this.validate().catch(err => {
console.error('Error running validation:', err)
})
}

treemode._renderValidationErrors = function (errorNodes) {
// clear all current errors
if (this.errorNodes) {
Expand Down
3 changes: 3 additions & 0 deletions src/scss/jsoneditor/_editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ div {
margin: 0 4px 0 0;
background-image: $jse-icons-url;
background-position: -168px -48px;
background-color: transparent;
}
}
}
Expand Down Expand Up @@ -536,11 +537,13 @@ pre.jsoneditor-preview,
.jsoneditor-schema-error {
background-image: $jse-icons-url;
background-position: -168px -48px;
background-color: transparent;
}
&.parse-error {
.jsoneditor-schema-error {
background-image: $jse-icons-url;
background-position: -25px 0px;
background-color: transparent;
}
}
}
Expand Down
20 changes: 15 additions & 5 deletions test/test_schema.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,29 @@
};

var options = {
mode: 'tree',
mode: 'code',
modes: ['code', 'form', 'text', 'tree', 'view', 'preview'], // allowed modes
schema: schema,
schemaRefs: {"hobbies.json": hobbiesSchema},
onError: function (err) {
console.error(err);
console.error('ERROR', err);
},
schema: schema,
schemaRefs: {"hobbies.json": hobbiesSchema}
onChange: async () => {
const errors = await editor.validate()
if (errors.length === 0) {
console.log('validation errors: NONE')
// do something, like persisting the JSON
} else {
// show error to the user or something
console.log('validation errors', errors)
}
}
};

var json = {
"firstName": "Jos",
"lastName": "de Jong",
gender: null,
"gender": null,
"age": 34.2,
"hobbies": [
"programming",
Expand Down

0 comments on commit b76c57a

Please sign in to comment.