A few more files refactored to ES modules

This commit is contained in:
jos 2019-08-31 11:21:29 +02:00
parent f321eb54ee
commit b79885471e
15 changed files with 356 additions and 323 deletions

View File

@ -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.

View File

@ -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)

View File

@ -1 +1 @@
module.exports = require('./src/js/JSONEditor').default
module.exports = require('./src/js/JSONEditor')

View File

@ -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])

View File

@ -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

View File

@ -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(/&lt;/g, '<')
@ -4514,4 +4537,4 @@ function hasOwnProperty (object, key) {
var AppendNode = appendNodeFactory(Node)
var ShowMoreNode = showMoreNodeFactory(Node)
module.exports = Node
export default Node

View File

@ -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

View File

@ -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'

View File

@ -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'

View File

@ -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,

View File

@ -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'
}

View File

@ -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', () => {

View File

@ -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', () => {

View File

@ -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()

View File

@ -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