diff --git a/app/common/prettify.js b/app/common/prettify.js new file mode 100644 index 0000000000..a7e0c51ca6 --- /dev/null +++ b/app/common/prettify.js @@ -0,0 +1,97 @@ +/** + * Format a JSON string without parsing it as JavaScript. + * + * Code taken from jsonlint (http://zaa.ch/jsonlint/) + * + * @param json + * @param indentChars + * @returns {string} + */ +export function prettifyJson (json, indentChars) { + let i = 0; + let il = json.length; + let tab = (typeof indentChars !== 'undefined') ? indentChars : ' '; + let newJson = ''; + let indentLevel = 0; + let inString = false; + let currentChar = null; + let previousChar = null; + let nextChar = null; + + for (;i < il; i += 1) { + currentChar = json.charAt(i); + previousChar = json.charAt(i - 1); + nextChar = json.charAt(i + 1); + + switch (currentChar) { + case '{': + if (!inString && nextChar !== '}') { + newJson += currentChar + '\n' + _repeatString(tab, indentLevel + 1); + indentLevel += 1; + } else { + newJson += currentChar; + } + break; + case '[': + if (!inString && nextChar !== ']') { + newJson += currentChar + '\n' + _repeatString(tab, indentLevel + 1); + indentLevel += 1; + } else { + newJson += currentChar; + } + break; + case '}': + if (!inString && previousChar !== '{') { + indentLevel -= 1; + newJson += '\n' + _repeatString(tab, indentLevel) + currentChar; + } else { + newJson += currentChar; + } + break; + case ']': + if (!inString && previousChar !== '[') { + indentLevel -= 1; + newJson += '\n' + _repeatString(tab, indentLevel) + currentChar; + } else { + newJson += currentChar; + } + break; + case ',': + if (!inString) { + newJson += ',\n' + _repeatString(tab, indentLevel); + } else { + newJson += currentChar; + } + break; + case ':': + if (!inString) { + newJson += ': '; + } else { + newJson += currentChar; + } + break; + case ' ': + case '\n': + case '\t': + if (inString) { + newJson += currentChar; + } + break; + case '"': + if (i > 0 && previousChar !== '\\') { + inString = !inString; + } + newJson += currentChar; + break; + default: + newJson += currentChar; + break; + } + } + + return newJson; +} + +function _repeatString(s, count) { + return new Array(count + 1).join(s); +} diff --git a/app/ui/components/base/Editor.js b/app/ui/components/base/Editor.js index bc91c9db17..9f9ff6f65d 100644 --- a/app/ui/components/base/Editor.js +++ b/app/ui/components/base/Editor.js @@ -49,6 +49,7 @@ import * as misc from '../../../common/misc'; import {trackEvent} from '../../../analytics/index'; // Make jsonlint available to the jsonlint plugin import {parser as jsonlint} from 'jsonlint'; +import {prettifyJson} from '../../../common/prettify'; global.jsonlint = jsonlint; @@ -170,36 +171,37 @@ class Editor extends Component { this._prettify(this.codeMirror.getValue()); } - async _prettify (code) { + _prettify (code) { if (this._isXML(this.props.mode)) { - code = this._formatXML(code); + code = this._prettifyXML(code); } else { - code = this._formatJSON(code); + code = this._prettifyJSON(code); } this.codeMirror.setValue(code); } - _formatJSON (code) { + _prettifyJSON (code) { try { - let obj = JSON.parse(code); + let jsonString = code; if (this.props.updateFilter && this.state.filter) { + let obj = JSON.parse(code); try { - obj = jq.query(obj, this.state.filter); + jsonString = JSON.stringify(jq.query(obj, this.state.filter)); } catch (err) { - obj = '[]'; + jsonString = '[]'; } } - return vkBeautify.json(obj, '\t'); + return prettifyJson(jsonString, '\t'); } catch (e) { // That's Ok, just leave it return code; } } - _formatXML (code) { + _prettifyXML (code) { if (this.props.updateFilter && this.state.filter) { try { const dom = new DOMParser().parseFromString(code);