A few more files refactored to ES modules

This commit is contained in:
jos 2019-08-29 18:31:33 +02:00
parent 9ef44bda6b
commit f321eb54ee
7 changed files with 160 additions and 118 deletions

View File

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

View File

@ -1,19 +1,15 @@
'use strict'
let Ajv
try {
Ajv = require('ajv')
} catch (err) {
// no problem... when we need Ajv we will throw a neat exception
}
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 treemode = require('./treemode')
const textmode = require('./textmode')
const previewmode = require('./previewmode')
const treeModeMixins = require('./treemode').treeModeMixins
const textModeMixins = require('./textmode').textModeMixins
const previewModeMixins = require('./previewmode').previewModeMixins
const util = require('./util')
const { tryRequireAjv } = require('./tryRequireAjv')
const Ajv = tryRequireAjv()
if (typeof Promise === 'undefined') {
console.error('Promise undefined. Please load a Promise polyfill in the browser in order to use JSONEditor')
@ -464,9 +460,9 @@ JSONEditor.registerMode = mode => {
}
// register tree, text, and preview modes
JSONEditor.registerMode(treemode)
JSONEditor.registerMode(textmode)
JSONEditor.registerMode(previewmode)
JSONEditor.registerMode(treeModeMixins)
JSONEditor.registerMode(textModeMixins)
JSONEditor.registerMode(previewModeMixins)
// expose some of the libraries that can be used customized
JSONEditor.ace = ace

View File

@ -1,18 +1,29 @@
'use strict'
const jmespath = require('jmespath')
const translate = require('./i18n').translate
const ModeSwitcher = require('./ModeSwitcher')
const ErrorTable = require('./ErrorTable')
const textmode = require('./textmode')[0].mixin
const showSortModal = require('./showSortModal').showSortModal
const showTransformModal = require('./showTransformModal').showTransformModal
const MAX_PREVIEW_CHARACTERS = require('./constants').MAX_PREVIEW_CHARACTERS
const DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR
const SIZE_LARGE = require('./constants').SIZE_LARGE
const PREVIEW_HISTORY_LIMIT = require('./constants').PREVIEW_HISTORY_LIMIT
const util = require('./util')
const History = require('./History').History
import jmespath from 'jmespath'
import { translate } from './i18n'
import ModeSwitcher from './ModeSwitcher'
import { ErrorTable } from './ErrorTable'
import { showSortModal } from './showSortModal'
import { showTransformModal } from './showTransformModal'
import { textModeMixins } from './textmode'
import { DEFAULT_MODAL_ANCHOR, MAX_PREVIEW_CHARACTERS, PREVIEW_HISTORY_LIMIT, SIZE_LARGE } from './constants'
import {
addClassName,
debounce,
escapeUnicodeChars,
formatSize,
isObject,
limitCharacters,
parse,
removeClassName,
repair,
sort,
sortObjectKeys
} from './util'
import { History } from './History'
const textmode = textModeMixins[0].mixin
// create a mixin with the functions for text mode
const previewmode = {}
@ -55,7 +66,7 @@ previewmode.create = function (container, options = {}) {
// TODO: JSON Schema support
// create a debounced validate function
this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this._debouncedValidate = debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this.width = container.clientWidth
this.height = container.clientHeight
@ -84,7 +95,7 @@ previewmode.create = function (container, options = {}) {
this.content.appendChild(this.dom.previewContent)
if (this.options.mainMenuBar) {
util.addClassName(this.content, 'has-main-menu-bar')
addClassName(this.content, 'has-main-menu-bar')
// create menu
this.menu = document.createElement('div')
@ -240,7 +251,7 @@ previewmode.create = function (container, options = {}) {
this.container.appendChild(this.frame)
if (options.statusBar) {
util.addClassName(this.content, 'has-status-bar')
addClassName(this.content, 'has-status-bar')
const statusBar = document.createElement('div')
this.dom.statusBar = statusBar
@ -270,10 +281,10 @@ previewmode.create = function (container, options = {}) {
previewmode._renderPreview = function () {
const text = this.getText()
this.dom.previewText.nodeValue = util.limitCharacters(text, MAX_PREVIEW_CHARACTERS)
this.dom.previewText.nodeValue = limitCharacters(text, MAX_PREVIEW_CHARACTERS)
if (this.dom.fileSizeInfo) {
this.dom.fileSizeInfo.innerText = 'Size: ' + util.formatSize(text.length)
this.dom.fileSizeInfo.innerText = 'Size: ' + formatSize(text.length)
}
if (this.dom.arrayInfo) {
@ -332,14 +343,14 @@ previewmode._showSortModal = function () {
function onSort (json, sortedBy) {
if (Array.isArray(json)) {
const sortedArray = util.sort(json, sortedBy.path, sortedBy.direction)
const sortedArray = sort(json, sortedBy.path, sortedBy.direction)
me.sortedBy = sortedBy
me._setAndFireOnChange(sortedArray)
}
if (util.isObject(json)) {
const sortedObject = util.sortObjectKeys(json, sortedBy.direction)
if (isObject(json)) {
const sortedObject = sortObjectKeys(json, sortedBy.direction)
me.sortedBy = sortedBy
me._setAndFireOnChange(sortedObject)
@ -426,7 +437,7 @@ previewmode.format = function () {
*/
previewmode.repair = function () {
const text = this.getText()
const repairedText = util.repair(text)
const repairedText = repair(text)
this._setTextAndFireOnChange(repairedText)
}
@ -489,7 +500,7 @@ previewmode.get = function () {
if (this.json === undefined) {
const text = this.getText()
this.json = util.parse(text) // this can throw an error
this.json = parse(text) // this can throw an error
}
return this.json
@ -504,7 +515,7 @@ previewmode.getText = function () {
this.text = JSON.stringify(this.json, null, this.indentation)
if (this.options.escapeUnicode === true) {
this.text = util.escapeUnicodeChars(this.text)
this.text = escapeUnicodeChars(this.text)
}
}
@ -544,7 +555,7 @@ previewmode.updateText = function (jsonText) {
*/
previewmode._setText = function (jsonText, json) {
if (this.options.escapeUnicode === true) {
this.text = util.escapeUnicodeChars(jsonText)
this.text = escapeUnicodeChars(jsonText)
} else {
this.text = jsonText
}
@ -624,12 +635,12 @@ previewmode.executeWithBusyMessage = function (fn, message) {
if (size > SIZE_LARGE) {
const me = this
util.addClassName(me.frame, 'busy')
addClassName(me.frame, 'busy')
me.dom.busyContent.innerText = message
setTimeout(() => {
fn()
util.removeClassName(me.frame, 'busy')
removeClassName(me.frame, 'busy')
me.dom.busyContent.innerText = ''
}, 100)
} else {
@ -642,7 +653,7 @@ previewmode.validate = textmode.validate
previewmode._renderErrors = textmode._renderErrors
// define modes
module.exports = [
export const previewModeMixins = [
{
mode: 'preview',
mixin: previewmode,

View File

@ -1,15 +1,29 @@
'use strict'
const ace = require('./ace')
const jmespath = require('jmespath')
const translate = require('./i18n').translate
const ModeSwitcher = require('./ModeSwitcher')
const ErrorTable = require('./ErrorTable').ErrorTable
const validateCustom = require('./validationUtils').validateCustom
const showSortModal = require('./showSortModal').showSortModal
const showTransformModal = require('./showTransformModal').showTransformModal
const util = require('./util')
const DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR
import ace from './ace'
import jmespath from 'jmespath'
import { translate } from './i18n'
import ModeSwitcher from './ModeSwitcher'
import { ErrorTable } from './ErrorTable'
import { validateCustom } from './validationUtils'
import { showSortModal } from './showSortModal'
import { showTransformModal } from './showTransformModal'
import {
addClassName,
debounce,
escapeUnicodeChars,
getIndexForPosition,
getInputSelection,
getPositionForPath,
improveSchemaError,
isObject,
parse,
repair,
sort,
sortObjectKeys
} from './util'
import { DEFAULT_MODAL_ANCHOR } from './constants'
import { tryRequireThemeJsonEditor } from './tryRequireThemeJsonEditor'
// create a mixin with the functions for text mode
const textmode = {}
@ -22,10 +36,7 @@ const DEFAULT_THEME = 'ace/theme/jsoneditor'
* @param {Object} [options] Object with options. See docs for details.
* @private
*/
textmode.create = function (container, options) {
// read options
options = options || {}
textmode.create = function (container, options = {}) {
if (typeof options.statusBar === 'undefined') {
options.statusBar = true
}
@ -61,11 +72,7 @@ textmode.create = function (container, options) {
// determine theme
this.theme = options.theme || DEFAULT_THEME
if (this.theme === DEFAULT_THEME && _ace) {
try {
require('./ace/theme-jsoneditor')
} catch (err) {
console.error(err)
}
tryRequireThemeJsonEditor()
}
if (options.onTextSelectionChange) {
@ -81,7 +88,7 @@ textmode.create = function (container, options) {
this.annotations = []
// create a debounced validate function
this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this._debouncedValidate = debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this.width = container.clientWidth
this.height = container.clientHeight
@ -100,7 +107,7 @@ textmode.create = function (container, options) {
this.content.className = 'jsoneditor-outer'
if (this.options.mainMenuBar) {
util.addClassName(this.content, 'has-main-menu-bar')
addClassName(this.content, 'has-main-menu-bar')
// create menu
this.menu = document.createElement('div')
@ -284,7 +291,7 @@ textmode.create = function (container, options) {
this.frame.appendChild(this.errorTable.getErrorTable())
if (options.statusBar) {
util.addClassName(this.content, 'has-status-bar')
addClassName(this.content, 'has-status-bar')
this.curserInfoElements = {}
const statusBar = document.createElement('div')
@ -385,14 +392,14 @@ textmode._showSortModal = function () {
function onSort (sortedBy) {
if (Array.isArray(json)) {
const sortedJson = util.sort(json, sortedBy.path, sortedBy.direction)
const sortedJson = sort(json, sortedBy.path, sortedBy.direction)
me.sortedBy = sortedBy
me.set(sortedJson)
}
if (util.isObject(json)) {
const sortedJson = util.sortObjectKeys(json, sortedBy.direction)
if (isObject(json)) {
const sortedJson = sortObjectKeys(json, sortedBy.direction)
me.sortedBy = sortedBy
me.set(sortedJson)
@ -490,7 +497,7 @@ textmode._updateCursorInfo = function () {
if (this.textarea) {
setTimeout(() => { // this to verify we get the most updated textarea cursor selection
const selectionRange = util.getInputSelection(me.textarea)
const selectionRange = getInputSelection(me.textarea)
if (selectionRange.startIndex !== selectionRange.endIndex) {
count = selectionRange.endIndex - selectionRange.startIndex
@ -617,7 +624,7 @@ textmode.format = function () {
*/
textmode.repair = function () {
const text = this.getText()
const repairedText = util.repair(text)
const repairedText = repair(text)
this._setText(repairedText, false)
}
@ -666,7 +673,7 @@ textmode.update = function (json) {
textmode.get = function () {
const text = this.getText()
return util.parse(text) // this can throw an error
return parse(text) // this can throw an error
}
/**
@ -693,7 +700,7 @@ textmode._setText = function (jsonText, clearHistory) {
let text
if (this.options.escapeUnicode === true) {
text = util.escapeUnicodeChars(jsonText)
text = escapeUnicodeChars(jsonText)
} else {
text = jsonText
}
@ -759,7 +766,7 @@ textmode.validate = function () {
if (!valid) {
schemaErrors = this.validateSchema.errors.map(error => {
error.type = 'validation'
return util.improveSchemaError(error)
return improveSchemaError(error)
})
}
}
@ -808,7 +815,7 @@ textmode._renderErrors = function (errors) {
}
return acc
}, errorPaths)
const errorLocations = util.getPositionForPath(jsonText, errorPaths)
const errorLocations = getPositionForPath(jsonText, errorPaths)
// render annotations in Ace Editor (if any)
if (this.aceEditor) {
@ -847,7 +854,7 @@ textmode._renderErrors = function (errors) {
textmode.getTextSelection = function () {
let selection = {}
if (this.textarea) {
const selectionRange = util.getInputSelection(this.textarea)
const selectionRange = getInputSelection(this.textarea)
if (this.cursorInfo && this.cursorInfo.line === selectionRange.end.row && this.cursorInfo.column === selectionRange.end.column) {
// selection direction is bottom => up
@ -900,7 +907,7 @@ textmode.getTextSelection = function () {
*/
textmode.onTextSelectionChange = function (callback) {
if (typeof callback === 'function') {
this._selectionChangedHandler = util.debounce(callback, this.DEBOUNCE_INTERVAL)
this._selectionChangedHandler = debounce(callback, this.DEBOUNCE_INTERVAL)
}
}
@ -913,8 +920,8 @@ textmode.setTextSelection = function (startPos, endPos) {
if (!startPos || !endPos) return
if (this.textarea) {
const startIndex = util.getIndexForPosition(this.textarea, startPos.row, startPos.column)
const endIndex = util.getIndexForPosition(this.textarea, endPos.row, endPos.column)
const startIndex = getIndexForPosition(this.textarea, startPos.row, startPos.column)
const endIndex = getIndexForPosition(this.textarea, endPos.row, endPos.column)
if (startIndex > -1 && endIndex > -1) {
if (this.textarea.setSelectionRange) {
this.textarea.focus()
@ -956,7 +963,7 @@ function load () {
}
// define modes
module.exports = [
export const textModeMixins = [
{
mode: 'text',
mixin: textmode,

View File

@ -1,18 +1,32 @@
'use strict'
const VanillaPicker = require('./vanilla-picker')
const Highlighter = require('./Highlighter').Highlighter
const NodeHistory = require('./NodeHistory').NodeHistory
const SearchBox = require('./SearchBox').SearchBox
const ContextMenu = require('./ContextMenu').ContextMenu
const TreePath = require('./TreePath').TreePath
const Node = require('./Node')
const ModeSwitcher = require('./ModeSwitcher')
const util = require('./util')
const autocomplete = require('./autocomplete').autocomplete
const translate = require('./i18n').translate
const setLanguages = require('./i18n').setLanguages
const setLanguage = require('./i18n').setLanguage
import VanillaPicker from './vanilla-picker'
import { Highlighter } from './Highlighter'
import { NodeHistory } from './NodeHistory'
import { SearchBox } from './SearchBox'
import { ContextMenu } from './ContextMenu'
import { TreePath } from './TreePath'
import Node from './Node'
import ModeSwitcher from './ModeSwitcher'
import {
addClassName,
addEventListener,
debounce,
getAbsoluteTop,
getSelectionOffset,
hasParentNode,
improveSchemaError,
isPromise,
isValidValidationError,
parse,
removeClassName,
removeEventListener,
repair,
selectContentEditable,
setSelectionOffset
} from './util'
import { autocomplete } from './autocomplete'
import { setLanguage, setLanguages, translate } from './i18n'
// create a mixin with the functions for tree mode
const treemode = {}
@ -144,7 +158,7 @@ treemode._setOptions = function (options) {
this.setSchema(this.options.schema, this.options.schemaRefs)
// create a debounced validate function
this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
this._debouncedValidate = debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL)
if (options.onSelectionChange) {
this.onSelectionChange(options.onSelectionChange)
@ -268,13 +282,13 @@ treemode.getText = function () {
*/
treemode.setText = function (jsonText) {
try {
this.set(util.parse(jsonText)) // this can throw an error
this.set(parse(jsonText)) // this can throw an error
} catch (err) {
// try to repair json, replace JavaScript notation with JSON notation
const repairedJsonText = util.repair(jsonText)
const repairedJsonText = repair(jsonText)
// try to parse again
this.set(util.parse(repairedJsonText)) // this can throw an error
this.set(parse(repairedJsonText)) // this can throw an error
}
}
@ -285,13 +299,13 @@ treemode.setText = function (jsonText) {
*/
treemode.updateText = function (jsonText) {
try {
this.update(util.parse(jsonText)) // this can throw an error
this.update(parse(jsonText)) // this can throw an error
} catch (err) {
// try to repair json, replace JavaScript notation with JSON notation
const repairJsonText = util.repair(jsonText)
const repairJsonText = repair(jsonText)
// try to parse again
this.update(util.parse(repairJsonText)) // this can throw an error
this.update(parse(repairJsonText)) // this can throw an error
}
}
@ -531,7 +545,7 @@ treemode.validate = function () {
if (!valid) {
// apply all new errors
schemaErrors = this.validateSchema.errors
.map(error => util.improveSchemaError(error))
.map(error => improveSchemaError(error))
.map(function findNode (error) {
return {
node: root.findNode(error.dataPath),
@ -610,7 +624,7 @@ treemode._validateCustom = function (json) {
const root = this.node
const customValidateResults = this.options.onValidate(json)
const resultPromise = util.isPromise(customValidateResults)
const resultPromise = isPromise(customValidateResults)
? customValidateResults
: Promise.resolve(customValidateResults)
@ -618,7 +632,7 @@ treemode._validateCustom = function (json) {
if (Array.isArray(customValidationPathErrors)) {
return customValidationPathErrors
.filter(error => {
const valid = util.isValidValidationError(error)
const valid = isValidValidationError(error)
if (!valid) {
console.warn('Ignoring a custom validation error with invalid structure. ' +
@ -674,7 +688,7 @@ treemode.refresh = function () {
treemode.startAutoScroll = function (mouseY) {
const me = this
const content = this.scrollableContent
const top = util.getAbsoluteTop(content)
const top = getAbsoluteTop(content)
const height = content.clientHeight
const bottom = top + height
const margin = 24
@ -752,7 +766,7 @@ treemode.setDomSelection = function (selection) {
: null
if (selection.range && container) {
const range = Object.assign({}, selection.range, { container: container })
util.setSelectionOffset(range)
setSelectionOffset(range)
} else if (node) { // just a fallback
node.focus()
}
@ -778,7 +792,7 @@ treemode.getDomSelection = function () {
? Object.keys(node.dom).find(domName => node.dom[domName] === focusTarget)
: null
let range = util.getSelectionOffset()
let range = getSelectionOffset()
if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs)
range = null
}
@ -903,13 +917,13 @@ treemode._createFrame = function () {
// Note: focus and blur events do not propagate, therefore they defined
// using an eventListener with useCapture=true
// see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
util.addEventListener(this.frame, 'focus', onEvent, true)
util.addEventListener(this.frame, 'blur', onEvent, true)
addEventListener(this.frame, 'focus', onEvent, true)
addEventListener(this.frame, 'blur', onEvent, true)
this.frame.onfocusin = onEvent // for IE
this.frame.onfocusout = onEvent // for IE
if (this.options.mainMenuBar) {
util.addClassName(this.contentOuter, 'has-main-menu-bar')
addClassName(this.contentOuter, 'has-main-menu-bar')
// create menu
this.menu = document.createElement('div')
@ -1108,7 +1122,7 @@ treemode._onEvent = function (event) {
}
} else {
// filter mouse events in the contents part of the editor (not the main menu)
if (event.type === 'mousedown' && util.hasParentNode(event.target, this.content)) {
if (event.type === 'mousedown' && hasParentNode(event.target, this.content)) {
this.deselect()
if (node && event.target === node.dom.drag) {
@ -1133,7 +1147,7 @@ treemode._onEvent = function (event) {
*/
treemode._updateTreePath = function (pathNodes) {
if (pathNodes && pathNodes.length) {
util.removeClassName(this.navBar, 'nav-bar-empty')
removeClassName(this.navBar, 'nav-bar-empty')
const pathObjs = []
pathNodes.forEach(node => {
@ -1154,7 +1168,7 @@ treemode._updateTreePath = function (pathNodes) {
})
this.treePath.setPath(pathObjs)
} else {
util.addClassName(this.navBar, 'nav-bar-empty')
addClassName(this.navBar, 'nav-bar-empty')
}
function getName (node) {
@ -1245,12 +1259,12 @@ treemode._onMultiSelectStart = function (event) {
const editor = this
if (!this.mousemove) {
this.mousemove = util.addEventListener(window, 'mousemove', event => {
this.mousemove = addEventListener(window, 'mousemove', event => {
editor._onMultiSelect(event)
})
}
if (!this.mouseup) {
this.mouseup = util.addEventListener(window, 'mouseup', event => {
this.mouseup = addEventListener(window, 'mouseup', event => {
editor._onMultiSelectEnd(event)
})
}
@ -1316,11 +1330,11 @@ treemode._onMultiSelectEnd = function () {
// cleanup global event listeners
if (this.mousemove) {
util.removeEventListener(window, 'mousemove', this.mousemove)
removeEventListener(window, 'mousemove', this.mousemove)
delete this.mousemove
}
if (this.mouseup) {
util.removeEventListener(window, 'mouseup', this.mouseup)
removeEventListener(window, 'mouseup', this.mouseup)
delete this.mouseup
}
}
@ -1480,7 +1494,7 @@ treemode._onKeyDown = function (event) {
const me = this
setTimeout(() => {
// select all text when moving focus to an editable div
util.selectContentEditable(me.focusTarget)
selectContentEditable(me.focusTarget)
}, 0)
}
@ -1535,7 +1549,7 @@ treemode._onKeyDown = function (event) {
*/
treemode._createTable = function () {
if (this.options.navigationBar) {
util.addClassName(this.contentOuter, 'has-nav-bar')
addClassName(this.contentOuter, 'has-nav-bar')
}
this.scrollableContent = document.createElement('div')
@ -1655,7 +1669,7 @@ treemode.getSelection = function () {
*/
treemode.onSelectionChange = function (callback) {
if (typeof callback === 'function') {
this._selectionChangedHandler = util.debounce(callback, this.DEBOUNCE_INTERVAL)
this._selectionChangedHandler = debounce(callback, this.DEBOUNCE_INTERVAL)
}
}
@ -1739,7 +1753,7 @@ treemode.getNodesByRange = function (start, end) {
}
// define modes
module.exports = [
export const treeModeMixins = [
{
mode: 'tree',
mixin: treemode,

7
src/js/tryRequireAjv.js Normal file
View File

@ -0,0 +1,7 @@
exports.tryRequireAjv = function () {
try {
return require('ajv')
} catch (err) {
// no problem... when we need Ajv we will throw a neat exception
}
}

View File

@ -0,0 +1,7 @@
exports.tryRequireThemeJsonEditor = function () {
try {
require('./ace/theme-jsoneditor')
} catch (err) {
console.error(err)
}
}