diff --git a/HISTORY.md b/HISTORY.md index c2487b8..988e197 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,8 +4,8 @@ https://github.com/josdejong/jsoneditor ## not yet published, version 7.0.0 +- Converted a large part of the code to ES6, put Babel transpiler in place. - Dropped support for bower, removed the `dist` folder from the git repository. -- Converted the code into ES6, put Babel transpiler in place. - Fixed #586: caret position lost when switching browser tabs. diff --git a/gulpfile.js b/gulpfile.js index eca11a7..eeab6a3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,40 +1,40 @@ -var fs = require('fs') -var path = require('path') -var gulp = require('gulp') -var log = require('fancy-log') -var format = require('date-format') -var concatCss = require('gulp-concat-css') -var minifyCSS = require('gulp-clean-css') -var sass = require('gulp-sass') -var mkdirp = require('mkdirp') -var webpack = require('webpack') -var uglify = require('uglify-js') +const fs = require('fs') +const path = require('path') +const gulp = require('gulp') +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 mkdirp = require('mkdirp') +const webpack = require('webpack') +const uglify = require('uglify-js') -var NAME = 'jsoneditor' -var NAME_MINIMALIST = 'jsoneditor-minimalist' -var ENTRY = './src/js/JSONEditor.js' -var HEADER = './src/js/header.js' -var IMAGE = './src/scss/img/jsoneditor-icons.svg' -var DOCS = './src/docs/*' -var DIST = path.join(__dirname, 'dist') +const NAME = 'jsoneditor' +const NAME_MINIMALIST = 'jsoneditor-minimalist' +const ENTRY = './src/js/JSONEditor.js' +const HEADER = './src/js/header.js' +const IMAGE = './src/scss/img/jsoneditor-icons.svg' +const DOCS = './src/docs/*' +const DIST = path.join(__dirname, 'dist') // generate banner with today's date and correct version function createBanner () { - var today = format.asString('yyyy-MM-dd', new Date()) // today, formatted as yyyy-MM-dd - var version = require('./package.json').version // math.js version + const today = format.asString('yyyy-MM-dd', new Date()) // today, formatted as yyyy-MM-dd + const version = require('./package.json').version // math.js version return String(fs.readFileSync(HEADER)) .replace('@@date', today) .replace('@@version', version) } -var bannerPlugin = new webpack.BannerPlugin({ +const bannerPlugin = new webpack.BannerPlugin({ banner: createBanner(), entryOnly: true, raw: true }) -var webpackConfigModule = { +const webpackConfigModule = { rules: [ { test: /\.m?js$/, @@ -47,7 +47,7 @@ var webpackConfigModule = { } // create a single instance of the compiler to allow caching -var compiler = webpack({ +const compiler = webpack({ entry: ENTRY, output: { library: 'JSONEditor', @@ -69,7 +69,7 @@ var compiler = webpack({ }) // create a single instance of the compiler to allow caching -var compilerMinimalist = webpack({ +const compilerMinimalist = webpack({ entry: ENTRY, output: { library: 'JSONEditor', @@ -92,8 +92,8 @@ var compilerMinimalist = webpack({ }) function minify (name) { - var code = String(fs.readFileSync(DIST + '/' + name + '.js')) - var result = uglify.minify(code, { + const code = String(fs.readFileSync(DIST + '/' + name + '.js')) + const result = uglify.minify(code, { sourceMap: { url: name + '.map' }, @@ -107,8 +107,8 @@ function minify (name) { throw result.error } - var fileMin = DIST + '/' + name + '.min.js' - var fileMap = DIST + '/' + name + '.map' + const fileMin = DIST + '/' + name + '.min.js' + const fileMap = DIST + '/' + name + '.map' fs.writeFileSync(fileMin, result.code) fs.writeFileSync(fileMap, result.map) diff --git a/index.js b/index.js index 2aedcda..2df7e5a 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -module.exports = require('./src/js/JSONEditor').default +module.exports = require('./src/js/JSONEditor') diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js index 6b4cc00..5de4c73 100644 --- a/src/js/JSONEditor.js +++ b/src/js/JSONEditor.js @@ -2,11 +2,10 @@ const ace = require('./ace') // may be undefined in case of minimalist bundle const VanillaPicker = require('./vanilla-picker') // may be undefined in case of minimalist bundle - -const treeModeMixins = require('./treemode').treeModeMixins -const textModeMixins = require('./textmode').textModeMixins -const previewModeMixins = require('./previewmode').previewModeMixins -const util = require('./util') +const { treeModeMixins } = require('./treemode') +const { textModeMixins } = require('./textmode') +const { previewModeMixins } = require('./previewmode') +const { clear, extend, getInternetExplorerVersion, parse } = require('./util') const { tryRequireAjv } = require('./tryRequireAjv') const Ajv = tryRequireAjv() @@ -97,7 +96,7 @@ function JSONEditor (container, options, json) { } // check for unsupported browser (IE8 and older) - const ieVersion = util.getInternetExplorerVersion() + const ieVersion = getInternetExplorerVersion() if (ieVersion !== -1 && ieVersion < 9) { throw new Error('Unsupported browser, IE9 or newer required. ' + 'Please install the newest version of your browser.') @@ -220,7 +219,7 @@ JSONEditor.prototype.get = function () { * @param {String | undefined} jsonText */ JSONEditor.prototype.setText = function (jsonText) { - this.json = util.parse(jsonText) + this.json = parse(jsonText) } /** @@ -263,7 +262,7 @@ JSONEditor.prototype.setMode = function (mode) { } const container = this.container - const options = util.extend({}, this.options) + const options = extend({}, this.options) const oldMode = options.mode let data let name @@ -277,8 +276,8 @@ JSONEditor.prototype.setMode = function (mode) { data = this[asText ? 'getText' : 'get']() // get text or json this.destroy() - util.clear(this) - util.extend(this, config.mixin) + clear(this) + extend(this, config.mixin) this.create(container, options) this.setName(name) @@ -428,7 +427,7 @@ JSONEditor.prototype.refresh = () => { JSONEditor.registerMode = mode => { let i, prop - if (util.isArray(mode)) { + if (Array.isArray(mode)) { // multiple modes for (i = 0; i < mode.length; i++) { JSONEditor.registerMode(mode[i]) diff --git a/src/js/ModeSwitcher.js b/src/js/ModeSwitcher.js index 5f946ec..118647a 100644 --- a/src/js/ModeSwitcher.js +++ b/src/js/ModeSwitcher.js @@ -1,7 +1,7 @@ 'use strict' -const ContextMenu = require('./ContextMenu').ContextMenu -const translate = require('./i18n').translate +import { ContextMenu } from './ContextMenu' +import { translate } from './i18n' /** * Create a select box to be used in the editor menu's, which allows to switch mode @@ -11,7 +11,7 @@ const translate = require('./i18n').translate * @param {function(mode: string)} onSwitch Callback invoked on switch * @constructor */ -function ModeSwitcher (container, modes, current, onSwitch) { +export function ModeSwitcher (container, modes, current, onSwitch) { // available modes const availableModes = { code: { @@ -119,5 +119,3 @@ ModeSwitcher.prototype.destroy = function () { } this.dom = null } - -module.exports = ModeSwitcher diff --git a/src/js/Node.js b/src/js/Node.js index 9da1e6c..212fc03 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -1,16 +1,39 @@ 'use strict' -const jmespath = require('jmespath') -const naturalSort = require('javascript-natural-sort') -const createAbsoluteAnchor = require('./createAbsoluteAnchor').createAbsoluteAnchor -const ContextMenu = require('./ContextMenu').ContextMenu -const appendNodeFactory = require('./appendNodeFactory') -const showMoreNodeFactory = require('./showMoreNodeFactory').showMoreNodeFactory -const showSortModal = require('./showSortModal').showSortModal -const showTransformModal = require('./showTransformModal').showTransformModal -const util = require('./util') -const translate = require('./i18n').translate -const DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR +import jmespath from 'jmespath' +import naturalSort from 'javascript-natural-sort' +import { createAbsoluteAnchor } from './createAbsoluteAnchor' +import { ContextMenu } from './ContextMenu' +import { appendNodeFactory } from './appendNodeFactory' +import { showMoreNodeFactory } from './showMoreNodeFactory' +import { showSortModal } from './showSortModal' +import { showTransformModal } from './showTransformModal' +import { + addClassName, + addEventListener, + debounce, + escapeUnicodeChars, + findUniqueName, + getAbsoluteLeft, + getAbsoluteTop, + getInnerText, + getType, + insideRect, + isUrl, + isValidColor, + makeFieldTooltip, + parse, + parsePath, + parseString, removeAllClassNames, + removeClassName, + removeEventListener, + selectContentEditable, + setEndOfContentEditable, + stripFormatting, + textDiff +} from './util' +import { translate } from './i18n' +import { DEFAULT_MODAL_ANCHOR } from './constants' const YEAR_2000 = 946684800000 @@ -44,8 +67,8 @@ function Node (editor, params) { this.setValue(null) } - this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL) - this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL) + this._debouncedOnChangeValue = debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL) + this._debouncedOnChangeField = debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL) // starting value for visible children this.visibleChilds = this.getMaxVisibleChilds() @@ -206,7 +229,7 @@ Node.prototype.serialize = function () { * @return {Node | null} Returns the Node when found, returns null if not found */ Node.prototype.findNode = function (jsonPath) { - const path = util.parsePath(jsonPath) + const path = parsePath(jsonPath) let node = this while (node && path.length > 0) { const prop = path.shift() @@ -265,7 +288,7 @@ Node.prototype.updateError = function () { const error = this.fieldError || this.valueError || this.error let tdError = this.dom.tdError if (error && this.dom && this.dom.tr) { - util.addClassName(this.dom.tr, 'jsoneditor-validation-error') + addClassName(this.dom.tr, 'jsoneditor-validation-error') if (!tdError) { tdError = document.createElement('td') @@ -292,7 +315,7 @@ Node.prototype.updateError = function () { const contentRect = this.editor.content.getBoundingClientRect() const popoverRect = popover.getBoundingClientRect() const margin = 20 // account for a scroll bar - const fit = util.insideRect(contentRect, popoverRect, margin) + const fit = insideRect(contentRect, popoverRect, margin) if (fit) { break @@ -322,7 +345,7 @@ Node.prototype.updateError = function () { tdError.appendChild(button) } else { if (this.dom.tr) { - util.removeClassName(this.dom.tr, 'jsoneditor-validation-error') + removeClassName(this.dom.tr, 'jsoneditor-validation-error') } if (tdError) { @@ -894,9 +917,9 @@ Node.prototype._updateCssClassName = function () { this.editor.options && typeof this.editor.options.onClassName === 'function' && this.dom.tree) { - util.removeAllClassNames(this.dom.tree) + removeAllClassNames(this.dom.tree) const addClasses = this.editor.options.onClassName({ path: this.getPath(), field: this.field, value: this.value }) || '' - util.addClassName(this.dom.tree, 'jsoneditor-values ' + addClasses) + addClassName(this.dom.tree, 'jsoneditor-values ' + addClasses) } } @@ -1209,10 +1232,10 @@ Node.prototype.focus = function (elementName) { dom.expand.focus() } else if (dom.field && this.fieldEditable) { dom.field.focus() - util.selectContentEditable(dom.field) + selectContentEditable(dom.field) } else if (dom.value && !this._hasChilds()) { dom.value.focus() - util.selectContentEditable(dom.value) + selectContentEditable(dom.value) } else { dom.menu.focus() } @@ -1221,10 +1244,10 @@ Node.prototype.focus = function (elementName) { case 'field': if (dom.field && this.fieldEditable) { dom.field.focus() - util.selectContentEditable(dom.field) + selectContentEditable(dom.field) } else if (dom.value && !this._hasChilds()) { dom.value.focus() - util.selectContentEditable(dom.value) + selectContentEditable(dom.value) } else if (this._hasChilds()) { dom.expand.focus() } else { @@ -1239,10 +1262,10 @@ Node.prototype.focus = function (elementName) { dom.select.focus() } else if (dom.value && !this._hasChilds()) { dom.value.focus() - util.selectContentEditable(dom.value) + selectContentEditable(dom.value) } else if (dom.field && this.fieldEditable) { dom.field.focus() - util.selectContentEditable(dom.field) + selectContentEditable(dom.field) } else if (this._hasChilds()) { dom.expand.focus() } else { @@ -1259,7 +1282,7 @@ Node.prototype.focus = function (elementName) { */ Node.select = editableDiv => { setTimeout(() => { - util.selectContentEditable(editableDiv) + selectContentEditable(editableDiv) }, 0) } @@ -1406,7 +1429,7 @@ Node.prototype.changeType = function (newType) { if (newType === 'string') { this.value = String(this.value) } else { - this.value = util.parseString(String(this.value)) + this.value = parseString(String(this.value)) } this.focus() @@ -1483,7 +1506,7 @@ Node.prototype._getDomValue = function () { this._clearValueError() if (this.dom.value && this.type !== 'array' && this.type !== 'object') { - this.valueInnerText = util.getInnerText(this.dom.value) + this.valueInnerText = getInnerText(this.dom.value) } if (this.valueInnerText !== undefined) { @@ -1494,7 +1517,7 @@ Node.prototype._getDomValue = function () { value = this._unescapeHTML(this.valueInnerText) } else { const str = this._unescapeHTML(this.valueInnerText) - value = util.parseString(str) + value = parseString(str) } if (value !== this.value) { this.value = value @@ -1554,13 +1577,13 @@ Node.prototype._onChangeValue = function () { // the added/removed text on undo/redo const oldSelection = this.editor.getDomSelection() if (oldSelection.range) { - const undoDiff = util.textDiff(String(this.value), String(this.previousValue)) + const undoDiff = textDiff(String(this.value), String(this.previousValue)) oldSelection.range.startOffset = undoDiff.start oldSelection.range.endOffset = undoDiff.end } const newSelection = this.editor.getDomSelection() if (newSelection.range) { - const redoDiff = util.textDiff(String(this.previousValue), String(this.value)) + const redoDiff = textDiff(String(this.previousValue), String(this.value)) newSelection.range.startOffset = redoDiff.start newSelection.range.endOffset = redoDiff.end } @@ -1586,13 +1609,13 @@ Node.prototype._onChangeField = function () { const oldSelection = this.editor.getDomSelection() const previous = this.previousField || '' if (oldSelection.range) { - const undoDiff = util.textDiff(this.field, previous) + const undoDiff = textDiff(this.field, previous) oldSelection.range.startOffset = undoDiff.start oldSelection.range.endOffset = undoDiff.end } const newSelection = this.editor.getDomSelection() if (newSelection.range) { - const redoDiff = util.textDiff(previous, this.field) + const redoDiff = textDiff(previous, this.field) newSelection.range.startOffset = redoDiff.start newSelection.range.endOffset = redoDiff.end } @@ -1623,10 +1646,10 @@ Node.prototype._updateDomValue = function () { // set text color depending on value type const value = this.value - const type = (this.type === 'auto') ? util.type(value) : this.type - const isUrl = type === 'string' && util.isUrl(value) - classNames.push('jsoneditor-' + type) - if (isUrl) { + const valueType = (this.type === 'auto') ? getType(value) : this.type + const valueIsUrl = valueType === 'string' && isUrl(value) + classNames.push('jsoneditor-' + valueType) + if (valueIsUrl) { classNames.push('jsoneditor-url') } @@ -1647,17 +1670,17 @@ Node.prototype._updateDomValue = function () { domValue.className = classNames.join(' ') // update title - if (type === 'array' || type === 'object') { + if (valueType === 'array' || valueType === 'object') { const count = this.childs ? this.childs.length : 0 domValue.title = this.type + ' containing ' + count + ' items' - } else if (isUrl && this.editable.value) { + } else if (valueIsUrl && this.editable.value) { domValue.title = translate('openUrl') } else { domValue.title = '' } // show checkbox when the value is a boolean - if (type === 'boolean' && this.editable.value) { + if (valueType === 'boolean' && this.editable.value) { if (!this.dom.checkbox) { this.dom.checkbox = document.createElement('input') this.dom.checkbox.type = 'checkbox' @@ -1738,7 +1761,7 @@ Node.prototype._updateDomValue = function () { if (this.editable.value && this.editor.options.colorPicker && typeof value === 'string' && - util.isValidColor(value)) { + isValidColor(value)) { if (!this.dom.color) { this.dom.color = document.createElement('div') this.dom.color.className = 'jsoneditor-color' @@ -1782,7 +1805,7 @@ Node.prototype._updateDomValue = function () { } // strip formatting from the contents of the editable div - util.stripFormatting(domValue) + stripFormatting(domValue) this._updateDomDefault() } @@ -1808,7 +1831,7 @@ Node.prototype._deleteDomColor = function () { Node.prototype._updateDomField = function () { const domField = this.dom.field if (domField) { - const tooltip = util.makeFieldTooltip(this.schema, this.editor.options.language) + const tooltip = makeFieldTooltip(this.schema, this.editor.options.language) if (tooltip) { domField.title = tooltip } @@ -1816,25 +1839,25 @@ Node.prototype._updateDomField = function () { // make backgound color lightgray when empty const isEmpty = (String(this.field) === '' && this.parent.type !== 'array') if (isEmpty) { - util.addClassName(domField, 'jsoneditor-empty') + addClassName(domField, 'jsoneditor-empty') } else { - util.removeClassName(domField, 'jsoneditor-empty') + removeClassName(domField, 'jsoneditor-empty') } // highlight when there is a search result if (this.searchFieldActive) { - util.addClassName(domField, 'jsoneditor-highlight-active') + addClassName(domField, 'jsoneditor-highlight-active') } else { - util.removeClassName(domField, 'jsoneditor-highlight-active') + removeClassName(domField, 'jsoneditor-highlight-active') } if (this.searchField) { - util.addClassName(domField, 'jsoneditor-highlight') + addClassName(domField, 'jsoneditor-highlight') } else { - util.removeClassName(domField, 'jsoneditor-highlight') + removeClassName(domField, 'jsoneditor-highlight') } // strip formatting from the contents of the editable div - util.stripFormatting(domField) + stripFormatting(domField) } } @@ -1848,7 +1871,7 @@ Node.prototype._getDomField = function (forceUnique) { this._clearFieldError() if (this.dom.field && this.fieldEditable) { - this.fieldInnerText = util.getInnerText(this.dom.field) + this.fieldInnerText = getInnerText(this.dom.field) } if (this.fieldInnerText !== undefined) { @@ -1866,7 +1889,7 @@ Node.prototype._getDomField = function (forceUnique) { } else { if (forceUnique) { // fix duplicate field: change it into a unique name - field = util.findUniqueName(field, existingFieldNames) + field = findUniqueName(field, existingFieldNames) if (field !== this.field) { this.field = field @@ -1906,12 +1929,12 @@ Node.prototype._updateDomDefault = function () { if (this.value === this.schema.default) { inputElement.title = translate('default') - util.addClassName(inputElement, 'jsoneditor-is-default') - util.removeClassName(inputElement, 'jsoneditor-is-not-default') + addClassName(inputElement, 'jsoneditor-is-default') + removeClassName(inputElement, 'jsoneditor-is-not-default') } else { inputElement.removeAttribute('title') - util.removeClassName(inputElement, 'jsoneditor-is-default') - util.addClassName(inputElement, 'jsoneditor-is-not-default') + removeClassName(inputElement, 'jsoneditor-is-default') + addClassName(inputElement, 'jsoneditor-is-not-default') } } @@ -2009,16 +2032,16 @@ Node.onDragStart = (nodes, event) => { // in case of multiple selected nodes, offsetY prevents the selection from // jumping when you start dragging one of the lower down nodes in the selection - const offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr) + const offsetY = getAbsoluteTop(draggedNode.dom.tr) - getAbsoluteTop(firstNode.dom.tr) if (!editor.mousemove) { - editor.mousemove = util.addEventListener(window, 'mousemove', event => { + editor.mousemove = addEventListener(window, 'mousemove', event => { Node.onDrag(nodes, event) }) } if (!editor.mouseup) { - editor.mouseup = util.addEventListener(window, 'mouseup', event => { + editor.mouseup = addEventListener(window, 'mouseup', event => { Node.onDragEnd(nodes, event) }) } @@ -2068,7 +2091,7 @@ Node.onDrag = (nodes, event) => { // move up/down const firstNode = nodes[0] const trThis = firstNode.dom.tr - let topThis = util.getAbsoluteTop(trThis) + let topThis = getAbsoluteTop(trThis) const heightThis = trThis.offsetHeight if (mouseY < topThis) { // move up @@ -2076,7 +2099,7 @@ Node.onDrag = (nodes, event) => { do { trPrev = trPrev.previousSibling nodePrev = Node.getNodeFromTarget(trPrev) - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0 + topPrev = trPrev ? getAbsoluteTop(trPrev) : 0 } while (trPrev && mouseY < topPrev) @@ -2097,7 +2120,7 @@ Node.onDrag = (nodes, event) => { if (nodePrev && nodePrev.isVisible()) { // check if mouseY is really inside the found node trPrev = nodePrev.dom.tr - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0 + topPrev = trPrev ? getAbsoluteTop(trPrev) : 0 if (mouseY > topPrev + heightThis) { nodePrev = undefined } @@ -2115,13 +2138,13 @@ Node.onDrag = (nodes, event) => { trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr trFirst = trLast ? trLast.nextSibling : undefined if (trFirst) { - topFirst = util.getAbsoluteTop(trFirst) + topFirst = getAbsoluteTop(trFirst) trNext = trFirst do { nodeNext = Node.getNodeFromTarget(trNext) if (trNext) { bottomNext = trNext.nextSibling - ? util.getAbsoluteTop(trNext.nextSibling) : 0 + ? getAbsoluteTop(trNext.nextSibling) : 0 heightNext = trNext ? (bottomNext - topFirst) : 0 if (nodeNext && @@ -2267,11 +2290,11 @@ Node.onDragEnd = (nodes, event) => { delete editor.drag if (editor.mousemove) { - util.removeEventListener(window, 'mousemove', editor.mousemove) + removeEventListener(window, 'mousemove', editor.mousemove) delete editor.mousemove } if (editor.mouseup) { - util.removeEventListener(window, 'mouseup', editor.mouseup) + removeEventListener(window, 'mouseup', editor.mouseup) delete editor.mouseup } @@ -2314,9 +2337,9 @@ Node.prototype._createDomField = () => document.createElement('div') Node.prototype.setHighlight = function (highlight) { if (this.dom.tr) { if (highlight) { - util.addClassName(this.dom.tr, 'jsoneditor-highlight') + addClassName(this.dom.tr, 'jsoneditor-highlight') } else { - util.removeClassName(this.dom.tr, 'jsoneditor-highlight') + removeClassName(this.dom.tr, 'jsoneditor-highlight') } if (this.append) { @@ -2341,15 +2364,15 @@ Node.prototype.setSelected = function (selected, isFirst) { if (this.dom.tr) { if (selected) { - util.addClassName(this.dom.tr, 'jsoneditor-selected') + addClassName(this.dom.tr, 'jsoneditor-selected') } else { - util.removeClassName(this.dom.tr, 'jsoneditor-selected') + removeClassName(this.dom.tr, 'jsoneditor-selected') } if (isFirst) { - util.addClassName(this.dom.tr, 'jsoneditor-first') + addClassName(this.dom.tr, 'jsoneditor-first') } else { - util.removeClassName(this.dom.tr, 'jsoneditor-first') + removeClassName(this.dom.tr, 'jsoneditor-first') } if (this.append) { @@ -2450,13 +2473,13 @@ Node.prototype.updateDom = function (options) { if (domValue) { if (this.type === 'array') { this.updateNodeName() - util.addClassName(this.dom.tr, 'jsoneditor-expandable') + addClassName(this.dom.tr, 'jsoneditor-expandable') } else if (this.type === 'object') { this.updateNodeName() - util.addClassName(this.dom.tr, 'jsoneditor-expandable') + addClassName(this.dom.tr, 'jsoneditor-expandable') } else { domValue.innerHTML = this._escapeHTML(this.value) - util.removeClassName(this.dom.tr, 'jsoneditor-expandable') + removeClassName(this.dom.tr, 'jsoneditor-expandable') } } @@ -2649,7 +2672,7 @@ Node.prototype._createDomValue = function () { domValue = document.createElement('div') domValue.innerHTML = '{...}' } else { - if (!this.editable.value && util.isUrl(this.value)) { + if (!this.editable.value && isUrl(this.value)) { // create a link in case of read-only editor and value containing an url domValue = document.createElement('a') domValue.href = this.value @@ -2770,9 +2793,9 @@ Node.prototype.onEvent = function (event) { const highlighter = node.editor.highlighter highlighter.highlight(node) highlighter.lock() - util.addClassName(dom.menu, 'jsoneditor-selected') + addClassName(dom.menu, 'jsoneditor-selected') this.showContextMenu(dom.menu, () => { - util.removeClassName(dom.menu, 'jsoneditor-selected') + removeClassName(dom.menu, 'jsoneditor-selected') highlighter.unlock() highlighter.unhighlight() }) @@ -2840,7 +2863,7 @@ Node.prototype.onEvent = function (event) { case 'click': if (event.ctrlKey && this.editable.value) { // if read-only, we use the regular click behavior of an anchor - if (util.isUrl(this.value)) { + if (isUrl(this.value)) { event.preventDefault() window.open(this.value, '_blank') } @@ -2911,16 +2934,16 @@ Node.prototype.onEvent = function (event) { if (domTree && target === domTree.parentNode && type === 'click' && !event.hasMoved) { const left = (event.offsetX !== undefined) ? (event.offsetX < (this.getLevel() + 1) * 24) - : (event.pageX < util.getAbsoluteLeft(dom.tdSeparator))// for FF + : (event.pageX < getAbsoluteLeft(dom.tdSeparator))// for FF if (left || expandable) { // node is expandable when it is an object or array if (domField) { - util.setEndOfContentEditable(domField) + setEndOfContentEditable(domField) domField.focus() } } else { if (domValue && !this.enum) { - util.setEndOfContentEditable(domValue) + setEndOfContentEditable(domValue) domValue.focus() } } @@ -2928,7 +2951,7 @@ Node.prototype.onEvent = function (event) { if (((target === dom.tdExpand && !expandable) || target === dom.tdField || target === dom.tdSeparator) && (type === 'click' && !event.hasMoved)) { if (domField) { - util.setEndOfContentEditable(domField) + setEndOfContentEditable(domField) domField.focus() } } @@ -2994,7 +3017,7 @@ Node.prototype.onKeyDown = function (event) { if (keynum === 13) { // Enter if (target === this.dom.value) { if (!this.editable.value || event.ctrlKey) { - if (util.isUrl(this.value)) { + if (isUrl(this.value)) { window.open(this.value, '_blank') handled = true } @@ -3430,7 +3453,7 @@ Node.onDuplicate = nodes => { const clone = node.clone() if (node.parent.type === 'object') { const existingFieldNames = node.parent.getFieldNames() - clone.field = util.findUniqueName(node.field, existingFieldNames) + clone.field = findUniqueName(node.field, existingFieldNames) } parent.insertAfter(clone, afterNode) afterNode = clone @@ -3589,7 +3612,7 @@ Node.prototype._onChangeType = function (newType) { */ Node.prototype.sort = function (path, direction) { if (typeof path === 'string') { - path = util.parsePath(path) + path = parsePath(path) } if (!this._hasChilds()) { @@ -4330,7 +4353,7 @@ Node.prototype.showSortModal = function () { function onSort (sortedBy) { const path = sortedBy.path - const pathArray = util.parsePath(path) + const pathArray = parsePath(path) node.sortedBy = sortedBy node.sort(pathArray, sortedBy.direction) @@ -4365,7 +4388,7 @@ Node.prototype._getType = value => { if (value instanceof Object) { return 'object' } - if (typeof (value) === 'string' && typeof (util.parseString(value)) !== 'string') { + if (typeof (value) === 'string' && typeof (parseString(value)) !== 'string') { return 'string' } @@ -4393,7 +4416,7 @@ Node.prototype._escapeHTML = function (text) { const json = JSON.stringify(htmlEscaped) let html = json.substring(1, json.length - 1) if (this.editor.options.escapeUnicode === true) { - html = util.escapeUnicodeChars(html) + html = escapeUnicodeChars(html) } return html } @@ -4407,7 +4430,7 @@ Node.prototype._escapeHTML = function (text) { */ Node.prototype._unescapeHTML = function (escapedText) { const json = '"' + this._escapeJSON(escapedText) + '"' - const htmlEscaped = util.parse(json) + const htmlEscaped = parse(json) return htmlEscaped .replace(/</g, '<') @@ -4514,4 +4537,4 @@ function hasOwnProperty (object, key) { var AppendNode = appendNodeFactory(Node) var ShowMoreNode = showMoreNodeFactory(Node) -module.exports = Node +export default Node diff --git a/src/js/appendNodeFactory.js b/src/js/appendNodeFactory.js index d013c60..74c51d1 100644 --- a/src/js/appendNodeFactory.js +++ b/src/js/appendNodeFactory.js @@ -1,14 +1,14 @@ 'use strict' -const util = require('./util') -const ContextMenu = require('./ContextMenu').ContextMenu -const translate = require('./i18n').translate +import { ContextMenu } from './ContextMenu' +import { translate } from './i18n' +import { addClassName, removeClassName } from './util' /** * A factory function to create an AppendNode, which depends on a Node * @param {Node} Node */ -function appendNodeFactory (Node) { +export function appendNodeFactory (Node) { /** * @constructor AppendNode * @extends Node @@ -234,9 +234,9 @@ function appendNodeFactory (Node) { const highlighter = this.editor.highlighter highlighter.highlight(this.parent) highlighter.lock() - util.addClassName(dom.menu, 'jsoneditor-selected') + addClassName(dom.menu, 'jsoneditor-selected') this.showContextMenu(dom.menu, () => { - util.removeClassName(dom.menu, 'jsoneditor-selected') + removeClassName(dom.menu, 'jsoneditor-selected') highlighter.unlock() highlighter.unhighlight() }) @@ -249,5 +249,3 @@ function appendNodeFactory (Node) { return AppendNode } - -module.exports = appendNodeFactory diff --git a/src/js/previewmode.js b/src/js/previewmode.js index 2d27d72..01b1a24 100644 --- a/src/js/previewmode.js +++ b/src/js/previewmode.js @@ -2,7 +2,7 @@ import jmespath from 'jmespath' import { translate } from './i18n' -import ModeSwitcher from './ModeSwitcher' +import { ModeSwitcher } from './ModeSwitcher' import { ErrorTable } from './ErrorTable' import { showSortModal } from './showSortModal' import { showTransformModal } from './showTransformModal' diff --git a/src/js/textmode.js b/src/js/textmode.js index d6940ee..806136f 100644 --- a/src/js/textmode.js +++ b/src/js/textmode.js @@ -3,7 +3,7 @@ import ace from './ace' import jmespath from 'jmespath' import { translate } from './i18n' -import ModeSwitcher from './ModeSwitcher' +import { ModeSwitcher } from './ModeSwitcher' import { ErrorTable } from './ErrorTable' import { validateCustom } from './validationUtils' import { showSortModal } from './showSortModal' diff --git a/src/js/treemode.js b/src/js/treemode.js index 8359eb2..8bca97f 100644 --- a/src/js/treemode.js +++ b/src/js/treemode.js @@ -7,7 +7,7 @@ import { SearchBox } from './SearchBox' import { ContextMenu } from './ContextMenu' import { TreePath } from './TreePath' import Node from './Node' -import ModeSwitcher from './ModeSwitcher' +import { ModeSwitcher } from './ModeSwitcher' import { addClassName, addEventListener, diff --git a/src/js/util.js b/src/js/util.js index 26bd301..ffb244a 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -341,7 +341,7 @@ export function clear (a) { * @param {*} object * @return {String} type */ -export function type (object) { +export function getType (object) { if (object === null) { return 'null' } diff --git a/test/Node.test.js b/test/Node.test.js index 97d2719..80a4120 100644 --- a/test/Node.test.js +++ b/test/Node.test.js @@ -1,8 +1,6 @@ -const assert = require('assert') -const setUpTestEnvironment = require('./setup') -setUpTestEnvironment() - -const Node = require('../src/js/Node') +import assert from 'assert' +import './setup' +import Node from '../src/js/Node' describe('Node', () => { describe('_findSchema', () => { diff --git a/test/jsonUtils.test.js b/test/jsonUtils.test.js index d654e36..391eed0 100644 --- a/test/jsonUtils.test.js +++ b/test/jsonUtils.test.js @@ -1,6 +1,5 @@ -const assert = require('assert') -const stringifyPartial = require('../src/js/jsonUtils').stringifyPartial -const containsArray = require('../src/js/jsonUtils').containsArray +import assert from 'assert' +import { stringifyPartial, containsArray } from '../src/js/jsonUtils' describe('jsonUtils', () => { it('should stringify a small object', () => { diff --git a/test/setup.js b/test/setup.js index c7801d5..a6ac342 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,11 +1,11 @@ -const JSDOM = require('jsdom').JSDOM +import { JSDOM } from 'jsdom' /** * Set up the test environment by simulating browser globals. * @param {string} [locale=en] A locale to set in navigator.language * @return {void} */ -module.exports = function setUpTestEnvironment (locale) { +function setUpTestEnvironment (locale) { if (!locale) { locale = 'en' } @@ -17,4 +17,6 @@ module.exports = function setUpTestEnvironment (locale) { // JSDom has no setter defined for navigator.language, so defineProperty is necessary in order to override it Object.defineProperty(navigator, 'language', { value: locale }) -} +}; + +setUpTestEnvironment() diff --git a/test/util.test.js b/test/util.test.js index ba3fc92..7f8e77f 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -1,93 +1,109 @@ -const assert = require('assert') -const util = require('../src/js/util') +import assert from 'assert' +import { + compileJSONPointer, + findUniqueName, + formatSize, + get, + getChildPaths, + getIndexForPosition, + isObject, + limitCharacters, + makeFieldTooltip, + parsePath, + parseString, + repair, + sort, + sortObjectKeys, + stringifyPath +} from '../src/js/util' describe('util', () => { describe('repair', () => { it('should leave valid JSON as is', () => { - assert.strictEqual(util.repair('{"a":2}'), '{"a":2}') + assert.strictEqual(repair('{"a":2}'), '{"a":2}') }) it('should replace JavaScript with JSON', () => { - assert.strictEqual(util.repair('{a:2}'), '{"a":2}') - assert.strictEqual(util.repair('{a: 2}'), '{"a": 2}') - assert.strictEqual(util.repair('{\n a: 2\n}'), '{\n "a": 2\n}') - assert.strictEqual(util.repair('{\'a\':2}'), '{"a":2}') - assert.strictEqual(util.repair('{a:\'foo\'}'), '{"a":"foo"}') - assert.strictEqual(util.repair('{a:\'foo\',b:\'bar\'}'), '{"a":"foo","b":"bar"}') + assert.strictEqual(repair('{a:2}'), '{"a":2}') + assert.strictEqual(repair('{a: 2}'), '{"a": 2}') + assert.strictEqual(repair('{\n a: 2\n}'), '{\n "a": 2\n}') + assert.strictEqual(repair('{\'a\':2}'), '{"a":2}') + assert.strictEqual(repair('{a:\'foo\'}'), '{"a":"foo"}') + assert.strictEqual(repair('{a:\'foo\',b:\'bar\'}'), '{"a":"foo","b":"bar"}') // should leave string content untouched - assert.strictEqual(util.repair('"{a:b}"'), '"{a:b}"') + assert.strictEqual(repair('"{a:b}"'), '"{a:b}"') }) it('should add/remove escape characters', () => { - assert.strictEqual(util.repair('"foo\'bar"'), '"foo\'bar"') - assert.strictEqual(util.repair('"foo\\"bar"'), '"foo\\"bar"') - assert.strictEqual(util.repair('\'foo"bar\''), '"foo\\"bar"') - assert.strictEqual(util.repair('\'foo\\\'bar\''), '"foo\'bar"') - assert.strictEqual(util.repair('"foo\\\'bar"'), '"foo\'bar"') + assert.strictEqual(repair('"foo\'bar"'), '"foo\'bar"') + assert.strictEqual(repair('"foo\\"bar"'), '"foo\\"bar"') + assert.strictEqual(repair('\'foo"bar\''), '"foo\\"bar"') + assert.strictEqual(repair('\'foo\\\'bar\''), '"foo\'bar"') + assert.strictEqual(repair('"foo\\\'bar"'), '"foo\'bar"') }) it('should replace special white characters', () => { - assert.strictEqual(util.repair('{"a":\u00a0"foo\u00a0bar"}'), '{"a": "foo\u00a0bar"}') - assert.strictEqual(util.repair('{"a":\u2009"foo"}'), '{"a": "foo"}') + assert.strictEqual(repair('{"a":\u00a0"foo\u00a0bar"}'), '{"a": "foo\u00a0bar"}') + assert.strictEqual(repair('{"a":\u2009"foo"}'), '{"a": "foo"}') }) it('should escape unescaped control characters', () => { - assert.strictEqual(util.repair('"hello\bworld"'), '"hello\\bworld"') - assert.strictEqual(util.repair('"hello\fworld"'), '"hello\\fworld"') - assert.strictEqual(util.repair('"hello\nworld"'), '"hello\\nworld"') - assert.strictEqual(util.repair('"hello\rworld"'), '"hello\\rworld"') - assert.strictEqual(util.repair('"hello\tworld"'), '"hello\\tworld"') - assert.strictEqual(util.repair('{"value\n": "dc=hcm,dc=com"}'), '{"value\\n": "dc=hcm,dc=com"}') + assert.strictEqual(repair('"hello\bworld"'), '"hello\\bworld"') + assert.strictEqual(repair('"hello\fworld"'), '"hello\\fworld"') + assert.strictEqual(repair('"hello\nworld"'), '"hello\\nworld"') + assert.strictEqual(repair('"hello\rworld"'), '"hello\\rworld"') + assert.strictEqual(repair('"hello\tworld"'), '"hello\\tworld"') + assert.strictEqual(repair('{"value\n": "dc=hcm,dc=com"}'), '{"value\\n": "dc=hcm,dc=com"}') }) it('should replace left/right quotes', () => { - assert.strictEqual(util.repair('\u2018foo\u2019'), '"foo"') - assert.strictEqual(util.repair('\u201Cfoo\u201D'), '"foo"') - assert.strictEqual(util.repair('\u0060foo\u00B4'), '"foo"') + assert.strictEqual(repair('\u2018foo\u2019'), '"foo"') + assert.strictEqual(repair('\u201Cfoo\u201D'), '"foo"') + assert.strictEqual(repair('\u0060foo\u00B4'), '"foo"') }) it('remove comments', () => { - assert.strictEqual(util.repair('/* foo */ {}'), ' {}') - assert.strictEqual(util.repair('/* foo */ {}'), ' {}') - assert.strictEqual(util.repair('{a:\'foo\',/*hello*/b:\'bar\'}'), '{"a":"foo","b":"bar"}') - assert.strictEqual(util.repair('{\na:\'foo\',//hello\nb:\'bar\'\n}'), '{\n"a":"foo",\n"b":"bar"\n}') + assert.strictEqual(repair('/* foo */ {}'), ' {}') + assert.strictEqual(repair('/* foo */ {}'), ' {}') + assert.strictEqual(repair('{a:\'foo\',/*hello*/b:\'bar\'}'), '{"a":"foo","b":"bar"}') + assert.strictEqual(repair('{\na:\'foo\',//hello\nb:\'bar\'\n}'), '{\n"a":"foo",\n"b":"bar"\n}') // should not remove comments in string - assert.strictEqual(util.repair('{"str":"/* foo */"}'), '{"str":"/* foo */"}') + assert.strictEqual(repair('{"str":"/* foo */"}'), '{"str":"/* foo */"}') }) it('should strip JSONP notation', () => { // matching - assert.strictEqual(util.repair('callback_123({});'), '{}') - assert.strictEqual(util.repair('callback_123([]);'), '[]') - assert.strictEqual(util.repair('callback_123(2);'), '2') - assert.strictEqual(util.repair('callback_123("foo");'), '"foo"') - assert.strictEqual(util.repair('callback_123(null);'), 'null') - assert.strictEqual(util.repair('callback_123(true);'), 'true') - assert.strictEqual(util.repair('callback_123(false);'), 'false') - assert.strictEqual(util.repair('/* foo bar */ callback_123 ({})'), '{}') - assert.strictEqual(util.repair('/* foo bar */ callback_123 ({})'), '{}') - assert.strictEqual(util.repair('/* foo bar */\ncallback_123({})'), '{}') - assert.strictEqual(util.repair('/* foo bar */ callback_123 ( {} )'), ' {} ') - assert.strictEqual(util.repair(' /* foo bar */ callback_123 ({}); '), '{}') - assert.strictEqual(util.repair('\n/* foo\nbar */\ncallback_123 ({});\n\n'), '{}') + assert.strictEqual(repair('callback_123({});'), '{}') + assert.strictEqual(repair('callback_123([]);'), '[]') + assert.strictEqual(repair('callback_123(2);'), '2') + assert.strictEqual(repair('callback_123("foo");'), '"foo"') + assert.strictEqual(repair('callback_123(null);'), 'null') + assert.strictEqual(repair('callback_123(true);'), 'true') + assert.strictEqual(repair('callback_123(false);'), 'false') + assert.strictEqual(repair('/* foo bar */ callback_123 ({})'), '{}') + assert.strictEqual(repair('/* foo bar */ callback_123 ({})'), '{}') + assert.strictEqual(repair('/* foo bar */\ncallback_123({})'), '{}') + assert.strictEqual(repair('/* foo bar */ callback_123 ( {} )'), ' {} ') + assert.strictEqual(repair(' /* foo bar */ callback_123 ({}); '), '{}') + assert.strictEqual(repair('\n/* foo\nbar */\ncallback_123 ({});\n\n'), '{}') // non-matching - assert.strictEqual(util.repair('callback {}'), 'callback {}') - assert.strictEqual(util.repair('callback({}'), 'callback({}') + assert.strictEqual(repair('callback {}'), 'callback {}') + assert.strictEqual(repair('callback({}'), 'callback({}') }) it('should strip trailing zeros', () => { // matching - assert.strictEqual(util.repair('[1,2,3,]'), '[1,2,3]') - assert.strictEqual(util.repair('[1,2,3,\n]'), '[1,2,3\n]') - assert.strictEqual(util.repair('[1,2,3, \n ]'), '[1,2,3 \n ]') - assert.strictEqual(util.repair('{"a":2,}'), '{"a":2}') + assert.strictEqual(repair('[1,2,3,]'), '[1,2,3]') + assert.strictEqual(repair('[1,2,3,\n]'), '[1,2,3\n]') + assert.strictEqual(repair('[1,2,3, \n ]'), '[1,2,3 \n ]') + assert.strictEqual(repair('{"a":2,}'), '{"a":2}') // not matching - assert.strictEqual(util.repair('"[1,2,3,]"'), '"[1,2,3,]"') - assert.strictEqual(util.repair('"{a:2,}"'), '"{a:2,}"') + assert.strictEqual(repair('"[1,2,3,]"'), '"[1,2,3,]"') + assert.strictEqual(repair('"{a:2,}"'), '"{a:2,}"') }) it('should strip MongoDB data types', () => { @@ -115,45 +131,45 @@ describe('util', () => { ' "decimal2" : 4\n' + '}' - assert.strictEqual(util.repair(mongoDocument), expectedJson) + assert.strictEqual(repair(mongoDocument), expectedJson) }) }) describe('jsonPath', () => { it('should stringify an array of paths', () => { - assert.deepStrictEqual(util.stringifyPath([]), '') - assert.deepStrictEqual(util.stringifyPath(['foo']), '.foo') - assert.deepStrictEqual(util.stringifyPath(['foo', 'bar']), '.foo.bar') - assert.deepStrictEqual(util.stringifyPath(['foo', 2]), '.foo[2]') - assert.deepStrictEqual(util.stringifyPath(['foo', 2, 'bar']), '.foo[2].bar') - assert.deepStrictEqual(util.stringifyPath(['foo', 2, 'bar_baz']), '.foo[2].bar_baz') - assert.deepStrictEqual(util.stringifyPath([2]), '[2]') - assert.deepStrictEqual(util.stringifyPath(['foo', 'prop-with-hyphens']), '.foo["prop-with-hyphens"]') - assert.deepStrictEqual(util.stringifyPath(['foo', 'prop with spaces']), '.foo["prop with spaces"]') + assert.deepStrictEqual(stringifyPath([]), '') + assert.deepStrictEqual(stringifyPath(['foo']), '.foo') + assert.deepStrictEqual(stringifyPath(['foo', 'bar']), '.foo.bar') + assert.deepStrictEqual(stringifyPath(['foo', 2]), '.foo[2]') + assert.deepStrictEqual(stringifyPath(['foo', 2, 'bar']), '.foo[2].bar') + assert.deepStrictEqual(stringifyPath(['foo', 2, 'bar_baz']), '.foo[2].bar_baz') + assert.deepStrictEqual(stringifyPath([2]), '[2]') + assert.deepStrictEqual(stringifyPath(['foo', 'prop-with-hyphens']), '.foo["prop-with-hyphens"]') + assert.deepStrictEqual(stringifyPath(['foo', 'prop with spaces']), '.foo["prop with spaces"]') }) it('should parse a json path', () => { - assert.deepStrictEqual(util.parsePath(''), []) - assert.deepStrictEqual(util.parsePath('.foo'), ['foo']) - assert.deepStrictEqual(util.parsePath('.foo.bar'), ['foo', 'bar']) - assert.deepStrictEqual(util.parsePath('.foo[2]'), ['foo', 2]) - assert.deepStrictEqual(util.parsePath('.foo[2].bar'), ['foo', 2, 'bar']) - assert.deepStrictEqual(util.parsePath('.foo["prop with spaces"]'), ['foo', 'prop with spaces']) - assert.deepStrictEqual(util.parsePath('.foo[\'prop with single quotes as outputted by ajv library\']'), ['foo', 'prop with single quotes as outputted by ajv library']) - assert.deepStrictEqual(util.parsePath('.foo["prop with . dot"]'), ['foo', 'prop with . dot']) - assert.deepStrictEqual(util.parsePath('.foo["prop with ] character"]'), ['foo', 'prop with ] character']) - assert.deepStrictEqual(util.parsePath('.foo[*].bar'), ['foo', '*', 'bar']) - assert.deepStrictEqual(util.parsePath('[2]'), [2]) + assert.deepStrictEqual(parsePath(''), []) + assert.deepStrictEqual(parsePath('.foo'), ['foo']) + assert.deepStrictEqual(parsePath('.foo.bar'), ['foo', 'bar']) + assert.deepStrictEqual(parsePath('.foo[2]'), ['foo', 2]) + assert.deepStrictEqual(parsePath('.foo[2].bar'), ['foo', 2, 'bar']) + assert.deepStrictEqual(parsePath('.foo["prop with spaces"]'), ['foo', 'prop with spaces']) + assert.deepStrictEqual(parsePath('.foo[\'prop with single quotes as outputted by ajv library\']'), ['foo', 'prop with single quotes as outputted by ajv library']) + assert.deepStrictEqual(parsePath('.foo["prop with . dot"]'), ['foo', 'prop with . dot']) + assert.deepStrictEqual(parsePath('.foo["prop with ] character"]'), ['foo', 'prop with ] character']) + assert.deepStrictEqual(parsePath('.foo[*].bar'), ['foo', '*', 'bar']) + assert.deepStrictEqual(parsePath('[2]'), [2]) }) it('should throw an exception in case of an invalid path', () => { - assert.throws(() => { util.parsePath('.') }, /Invalid JSON path: property name expected at index 1/) - assert.throws(() => { util.parsePath('[') }, /Invalid JSON path: unexpected end, character ] expected/) - assert.throws(() => { util.parsePath('[]') }, /Invalid JSON path: array value expected at index 1/) - assert.throws(() => { util.parsePath('.foo[ ]') }, /Invalid JSON path: array value expected at index 7/) - assert.throws(() => { util.parsePath('.[]') }, /Invalid JSON path: property name expected at index 1/) - assert.throws(() => { util.parsePath('["23]') }, /Invalid JSON path: unexpected end, character " expected/) - assert.throws(() => { util.parsePath('.foo bar') }, /Invalid JSON path: unexpected character " " at index 4/) + assert.throws(() => { parsePath('.') }, /Invalid JSON path: property name expected at index 1/) + assert.throws(() => { parsePath('[') }, /Invalid JSON path: unexpected end, character ] expected/) + assert.throws(() => { parsePath('[]') }, /Invalid JSON path: array value expected at index 1/) + assert.throws(() => { parsePath('.foo[ ]') }, /Invalid JSON path: array value expected at index 7/) + assert.throws(() => { parsePath('.[]') }, /Invalid JSON path: property name expected at index 1/) + assert.throws(() => { parsePath('["23]') }, /Invalid JSON path: unexpected end, character " expected/) + assert.throws(() => { parsePath('.foo bar') }, /Invalid JSON path: unexpected character " " at index 4/) }) }) @@ -163,23 +179,23 @@ describe('util', () => { } it('happy flows - row and column in range', () => { - assert.strictEqual(util.getIndexForPosition(el, 1, 1), 0) - assert.strictEqual(util.getIndexForPosition(el, 2, 1), 124) - assert.strictEqual(util.getIndexForPosition(el, 3, 8), 239) - assert.strictEqual(util.getIndexForPosition(el, 4, 22), 356) + assert.strictEqual(getIndexForPosition(el, 1, 1), 0) + assert.strictEqual(getIndexForPosition(el, 2, 1), 124) + assert.strictEqual(getIndexForPosition(el, 3, 8), 239) + assert.strictEqual(getIndexForPosition(el, 4, 22), 356) }) it('if range exceeds it should be considered as if it is last row or column length', () => { - assert.strictEqual(util.getIndexForPosition(el, 1, 100000), 123) - assert.strictEqual(util.getIndexForPosition(el, 100000, 1), 335) - assert.strictEqual(util.getIndexForPosition(el, 100000, 100000), 445) + assert.strictEqual(getIndexForPosition(el, 1, 100000), 123) + assert.strictEqual(getIndexForPosition(el, 100000, 1), 335) + assert.strictEqual(getIndexForPosition(el, 100000, 100000), 445) }) it('missing or wrong input sould return -1', () => { - assert.strictEqual(util.getIndexForPosition(el), -1) - assert.strictEqual(util.getIndexForPosition(el, undefined, 1), -1) - assert.strictEqual(util.getIndexForPosition(el, 1, undefined), -1) - assert.strictEqual(util.getIndexForPosition(el, -2, -2), -1) + assert.strictEqual(getIndexForPosition(el), -1) + assert.strictEqual(getIndexForPosition(el, undefined, 1), -1) + assert.strictEqual(getIndexForPosition(el, 1, undefined), -1) + assert.strictEqual(getIndexForPosition(el, -2, -2), -1) }) }) @@ -194,80 +210,80 @@ describe('util', () => { e: undefined } - assert.strictEqual(util.get(obj, ['a', 'b']), 2) - assert.strictEqual(util.get(obj, ['c']), 3) - assert.deepStrictEqual(util.get(obj, ['a']), { b: 2 }) - assert.strictEqual(util.get(obj, ['a', 'foo']), undefined) - assert.strictEqual(util.get(obj, ['a', 'foo', 'bar']), undefined) - assert.strictEqual(util.get(obj, ['d']), null) - assert.strictEqual(util.get(obj, ['d', 'foo', 'bar']), null) - assert.strictEqual(util.get(obj, ['e']), undefined) + assert.strictEqual(get(obj, ['a', 'b']), 2) + assert.strictEqual(get(obj, ['c']), 3) + assert.deepStrictEqual(get(obj, ['a']), { b: 2 }) + assert.strictEqual(get(obj, ['a', 'foo']), undefined) + assert.strictEqual(get(obj, ['a', 'foo', 'bar']), undefined) + assert.strictEqual(get(obj, ['d']), null) + assert.strictEqual(get(obj, ['d', 'foo', 'bar']), null) + assert.strictEqual(get(obj, ['e']), undefined) }) }) describe('makeFieldTooltip', () => { it('should return empty string when the schema is missing all relevant fields', () => { - assert.strictEqual(util.makeFieldTooltip({}), '') - assert.strictEqual(util.makeFieldTooltip({ additionalProperties: false }), '') - assert.strictEqual(util.makeFieldTooltip(), '') + assert.strictEqual(makeFieldTooltip({}), '') + assert.strictEqual(makeFieldTooltip({ additionalProperties: false }), '') + assert.strictEqual(makeFieldTooltip(), '') }) it('should make tooltips with only title', () => { - assert.strictEqual(util.makeFieldTooltip({ title: 'foo' }), 'foo') + assert.strictEqual(makeFieldTooltip({ title: 'foo' }), 'foo') }) it('should make tooltips with only description', () => { - assert.strictEqual(util.makeFieldTooltip({ description: 'foo' }), 'foo') + assert.strictEqual(makeFieldTooltip({ description: 'foo' }), 'foo') }) it('should make tooltips with only default', () => { - assert.strictEqual(util.makeFieldTooltip({ default: 'foo' }), 'Default\n"foo"') + assert.strictEqual(makeFieldTooltip({ default: 'foo' }), 'Default\n"foo"') }) it('should make tooltips with only examples', () => { - assert.strictEqual(util.makeFieldTooltip({ examples: ['foo', 'bar'] }), 'Examples\n"foo"\n"bar"') + assert.strictEqual(makeFieldTooltip({ examples: ['foo', 'bar'] }), 'Examples\n"foo"\n"bar"') }) it('should make tooltips with title and description', () => { - assert.strictEqual(util.makeFieldTooltip({ title: 'foo', description: 'bar' }), 'foo\nbar') + assert.strictEqual(makeFieldTooltip({ title: 'foo', description: 'bar' }), 'foo\nbar') const longTitle = 'Lorem Ipsum Dolor' const longDescription = 'Duis id elit non ante gravida vestibulum non nec est. ' + 'Proin vitae ligula at elit dapibus tempor. ' + 'Etiam lacinia augue vel condimentum interdum. ' assert.strictEqual( - util.makeFieldTooltip({ title: longTitle, description: longDescription }), + makeFieldTooltip({ title: longTitle, description: longDescription }), longTitle + '\n' + longDescription ) }) it('should make tooltips with title, description, and examples', () => { assert.strictEqual( - util.makeFieldTooltip({ title: 'foo', description: 'bar', examples: ['baz'] }), + makeFieldTooltip({ title: 'foo', description: 'bar', examples: ['baz'] }), 'foo\nbar\n\nExamples\n"baz"' ) }) it('should make tooltips with title, description, default, and examples', () => { assert.strictEqual( - util.makeFieldTooltip({ title: 'foo', description: 'bar', default: 'bat', examples: ['baz'] }), + makeFieldTooltip({ title: 'foo', description: 'bar', default: 'bat', examples: ['baz'] }), 'foo\nbar\n\nDefault\n"bat"\n\nExamples\n"baz"' ) }) it('should handle empty fields', () => { - assert.strictEqual(util.makeFieldTooltip({ title: '', description: 'bar' }), 'bar') - assert.strictEqual(util.makeFieldTooltip({ title: 'foo', description: '' }), 'foo') - assert.strictEqual(util.makeFieldTooltip({ description: 'bar', examples: [] }), 'bar') - assert.strictEqual(util.makeFieldTooltip({ description: 'bar', examples: [''] }), 'bar\n\nExamples\n""') + assert.strictEqual(makeFieldTooltip({ title: '', description: 'bar' }), 'bar') + assert.strictEqual(makeFieldTooltip({ title: 'foo', description: '' }), 'foo') + assert.strictEqual(makeFieldTooltip({ description: 'bar', examples: [] }), 'bar') + assert.strictEqual(makeFieldTooltip({ description: 'bar', examples: [''] }), 'bar\n\nExamples\n""') }) it('should internationalize "Defaults" correctly', () => { - assert.strictEqual(util.makeFieldTooltip({ default: 'foo' }, 'pt-BR'), 'Revelia\n"foo"') + assert.strictEqual(makeFieldTooltip({ default: 'foo' }, 'pt-BR'), 'Revelia\n"foo"') }) it('should internationalize "Examples" correctly', () => { - assert.strictEqual(util.makeFieldTooltip({ examples: ['foo'] }, 'pt-BR'), 'Exemplos\n"foo"') + assert.strictEqual(makeFieldTooltip({ examples: ['foo'] }, 'pt-BR'), 'Exemplos\n"foo"') }) }) @@ -279,7 +295,7 @@ describe('util', () => { { name: 'C', timestamp: 0 } ] - assert.deepStrictEqual(util.getChildPaths(json), [ + assert.deepStrictEqual(getChildPaths(json), [ '.location.latitude', '.location.longitude', '.name', @@ -294,7 +310,7 @@ describe('util', () => { { name: 'C', timestamp: 0 } ] - assert.deepStrictEqual(util.getChildPaths(json, true), [ + assert.deepStrictEqual(getChildPaths(json, true), [ '', '.location', '.location.latitude', @@ -307,33 +323,33 @@ describe('util', () => { it('should extract all child paths of an array containing values', () => { const json = [1, 2, 3] - assert.deepStrictEqual(util.getChildPaths(json), [ + assert.deepStrictEqual(getChildPaths(json), [ '' ]) }) it('should extract all child paths of a non-array', () => { - assert.deepStrictEqual(util.getChildPaths({ a: 2, b: { c: 3 } }), ['']) - assert.deepStrictEqual(util.getChildPaths('foo'), ['']) - assert.deepStrictEqual(util.getChildPaths(123), ['']) + assert.deepStrictEqual(getChildPaths({ a: 2, b: { c: 3 } }), ['']) + assert.deepStrictEqual(getChildPaths('foo'), ['']) + assert.deepStrictEqual(getChildPaths(123), ['']) }) }) it('should test whether something is an object', () => { - assert.strictEqual(util.isObject({}), true) - assert.strictEqual(util.isObject(new Date()), true) - assert.strictEqual(util.isObject([]), false) - assert.strictEqual(util.isObject(2), false) - assert.strictEqual(util.isObject(null), false) - assert.strictEqual(util.isObject(undefined), false) - assert.strictEqual(util.isObject(), false) + assert.strictEqual(isObject({}), true) + assert.strictEqual(isObject(new Date()), true) + assert.strictEqual(isObject([]), false) + assert.strictEqual(isObject(2), false) + assert.strictEqual(isObject(null), false) + assert.strictEqual(isObject(undefined), false) + assert.strictEqual(isObject(), false) }) describe('sort', () => { it('should sort an array', () => { const array = [4, 1, 10, 2] - assert.deepStrictEqual(util.sort(array), [1, 2, 4, 10]) - assert.deepStrictEqual(util.sort(array, '.', 'desc'), [10, 4, 2, 1]) + assert.deepStrictEqual(sort(array), [1, 2, 4, 10]) + assert.deepStrictEqual(sort(array, '.', 'desc'), [10, 4, 2, 1]) }) it('should sort an array containing objects', () => { @@ -344,14 +360,14 @@ describe('util', () => { { value: 2 } ] - assert.deepStrictEqual(util.sort(array, '.value'), [ + assert.deepStrictEqual(sort(array, '.value'), [ { value: 1 }, { value: 2 }, { value: 4 }, { value: 10 } ]) - assert.deepStrictEqual(util.sort(array, '.value', 'desc'), [ + assert.deepStrictEqual(sort(array, '.value', 'desc'), [ { value: 10 }, { value: 4 }, { value: 2 }, @@ -368,42 +384,42 @@ describe('util', () => { b: 'b' } assert.strictEqual(JSON.stringify(object), '{"c":"c","a":"a","b":"b"}') - assert.strictEqual(JSON.stringify(util.sortObjectKeys(object)), '{"a":"a","b":"b","c":"c"}') - assert.strictEqual(JSON.stringify(util.sortObjectKeys(object, 'asc')), '{"a":"a","b":"b","c":"c"}') - assert.strictEqual(JSON.stringify(util.sortObjectKeys(object, 'desc')), '{"c":"c","b":"b","a":"a"}') + assert.strictEqual(JSON.stringify(sortObjectKeys(object)), '{"a":"a","b":"b","c":"c"}') + assert.strictEqual(JSON.stringify(sortObjectKeys(object, 'asc')), '{"a":"a","b":"b","c":"c"}') + assert.strictEqual(JSON.stringify(sortObjectKeys(object, 'desc')), '{"c":"c","b":"b","a":"a"}') }) }) it('should parse a string', () => { - assert.strictEqual(util.parseString('foo'), 'foo') - assert.strictEqual(util.parseString('234foo'), '234foo') - assert.strictEqual(util.parseString('2.3'), 2.3) - assert.strictEqual(util.parseString('null'), null) - assert.strictEqual(util.parseString('true'), true) - assert.strictEqual(util.parseString('false'), false) + assert.strictEqual(parseString('foo'), 'foo') + assert.strictEqual(parseString('234foo'), '234foo') + assert.strictEqual(parseString('2.3'), 2.3) + assert.strictEqual(parseString('null'), null) + assert.strictEqual(parseString('true'), true) + assert.strictEqual(parseString('false'), false) }) it('should find a unique name', () => { - assert.strictEqual(util.findUniqueName('other', [ + assert.strictEqual(findUniqueName('other', [ 'a', 'b', 'c' ]), 'other') - assert.strictEqual(util.findUniqueName('b', [ + assert.strictEqual(findUniqueName('b', [ 'a', 'b', 'c' ]), 'b (copy)') - assert.strictEqual(util.findUniqueName('b', [ + assert.strictEqual(findUniqueName('b', [ 'a', 'b', 'c', 'b (copy)' ]), 'b (copy 2)') - assert.strictEqual(util.findUniqueName('b', [ + assert.strictEqual(findUniqueName('b', [ 'a', 'b', 'c', @@ -411,7 +427,7 @@ describe('util', () => { 'b (copy 2)' ]), 'b (copy 3)') - assert.strictEqual(util.findUniqueName('b (copy)', [ + assert.strictEqual(findUniqueName('b (copy)', [ 'a', 'b', 'b (copy)', @@ -419,7 +435,7 @@ describe('util', () => { 'c' ]), 'b (copy 3)') - assert.strictEqual(util.findUniqueName('b (copy 2)', [ + assert.strictEqual(findUniqueName('b (copy 2)', [ 'a', 'b', 'b (copy)', @@ -429,27 +445,27 @@ describe('util', () => { }) it('should format a document size in a human readable way', () => { - assert.strictEqual(util.formatSize(500), '500 B') - assert.strictEqual(util.formatSize(900), '0.9 KiB') - assert.strictEqual(util.formatSize(77.89 * 1024), '77.9 KiB') - assert.strictEqual(util.formatSize(950 * 1024), '0.9 MiB') - assert.strictEqual(util.formatSize(7.22 * 1024 * 1024), '7.2 MiB') - assert.strictEqual(util.formatSize(955.4 * 1024 * 1024), '0.9 GiB') - assert.strictEqual(util.formatSize(22.37 * 1024 * 1024 * 1024), '22.4 GiB') - assert.strictEqual(util.formatSize(1024 * 1024 * 1024 * 1024), '1.0 TiB') + assert.strictEqual(formatSize(500), '500 B') + assert.strictEqual(formatSize(900), '0.9 KiB') + assert.strictEqual(formatSize(77.89 * 1024), '77.9 KiB') + assert.strictEqual(formatSize(950 * 1024), '0.9 MiB') + assert.strictEqual(formatSize(7.22 * 1024 * 1024), '7.2 MiB') + assert.strictEqual(formatSize(955.4 * 1024 * 1024), '0.9 GiB') + assert.strictEqual(formatSize(22.37 * 1024 * 1024 * 1024), '22.4 GiB') + assert.strictEqual(formatSize(1024 * 1024 * 1024 * 1024), '1.0 TiB') }) it('should limit characters', () => { - assert.strictEqual(util.limitCharacters('hello world', 11), 'hello world') - assert.strictEqual(util.limitCharacters('hello world', 5), 'hello...') - assert.strictEqual(util.limitCharacters('hello world', 100), 'hello world') + assert.strictEqual(limitCharacters('hello world', 11), 'hello world') + assert.strictEqual(limitCharacters('hello world', 5), 'hello...') + assert.strictEqual(limitCharacters('hello world', 100), 'hello world') }) it('should compile a JSON pointer', () => { - assert.strictEqual(util.compileJSONPointer(['foo', 'bar']), '/foo/bar') - assert.strictEqual(util.compileJSONPointer(['foo', '/~ ~/']), '/foo/~1~0 ~0~1') - assert.strictEqual(util.compileJSONPointer(['']), '/') - assert.strictEqual(util.compileJSONPointer([]), '') + assert.strictEqual(compileJSONPointer(['foo', 'bar']), '/foo/bar') + assert.strictEqual(compileJSONPointer(['foo', '/~ ~/']), '/foo/~1~0 ~0~1') + assert.strictEqual(compileJSONPointer(['']), '/') + assert.strictEqual(compileJSONPointer([]), '') }) // TODO: thoroughly test all util methods